Live Trading working tested at Binance
This commit is contained in:
1 parent
1ba29a7bad
commit
15b8a9044d
63 files changed
+1675
-1970
No files matched your search
+69
-307
@@ -11,8 +11,7 @@
|
||||
let thisObject = {
|
||||
dataDependencies: undefined,
|
||||
initialize: initialize,
|
||||
putPosition: putPosition,
|
||||
movePosition: movePosition,
|
||||
createOrder: createOrder,
|
||||
getPositions: getPositions,
|
||||
getBalance: getBalance,
|
||||
getAvailableBalance: getAvailableBalance,
|
||||
@@ -32,7 +31,7 @@
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(logger);
|
||||
|
||||
let exchangePositions = []; // These are the open positions at the exchange at the account the bot is authorized to use.
|
||||
let openOrders = []; // These are the open positions at the exchange at the account the bot is authorized to use.
|
||||
let openPositions = []; // These are the open positions the bot knows it made by itself.
|
||||
|
||||
let context;
|
||||
@@ -63,16 +62,10 @@
|
||||
}
|
||||
|
||||
case 'Backtest': {
|
||||
// getMarketRateFromIndicator(); NOTE: This path is disabled since for now we do not allow ticker in simulation. Also it allow us to ship a dataset without bruce
|
||||
validateExchangeSyncronicity();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Competition': {
|
||||
getMarketRateFromExchange();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Unexpected bot.startMode.");
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> bot.startMode = " + bot.startMode);
|
||||
@@ -124,99 +117,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getMarketRateFromIndicator() {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromIndicator -> Entering function."); }
|
||||
|
||||
/* Procedure to get the current market rate. */
|
||||
|
||||
let key =
|
||||
bot.marketRateProvider.dataMine + "-" +
|
||||
bot.marketRateProvider.bot + "-" +
|
||||
bot.marketRateProvider.product + "-" +
|
||||
bot.marketRateProvider.dataSet + "-" +
|
||||
bot.marketRateProvider.dataSetVersion;
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromIndicator -> key = " + key); }
|
||||
|
||||
let dataSet = thisObject.dataDependencies.dataSets.get(key);
|
||||
|
||||
let dateForPath = bot.processDatetime.getUTCFullYear() + '/' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.processDatetime.getUTCDate(), 2);
|
||||
let fileName = '' + bot.market.baseAsset + '_' + bot.market.quotedAsset + '.json';
|
||||
let filePath = bot.marketRateProvider.product + "/" + bot.marketRateProvider.dataSet + "/" + dateForPath;
|
||||
|
||||
dataSet.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromIndicator -> onFileReceived -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromIndicator -> onFileReceived -> text = " + text); }
|
||||
|
||||
let candleArray;
|
||||
|
||||
if (err.result === global.CUSTOM_FAIL_RESPONSE.result || err.code === "The specified key does not exist." || err.message === "File does not exist.") { // Just past midnight, this file will not exist for a couple of minutes.
|
||||
|
||||
logger.write(MODULE_NAME, "[WARN] initialize -> getMarketRateFromIndicator -> onFileReceived -> err = " + JSON.stringify(err));
|
||||
logger.write(MODULE_NAME, "[WARN] initialize -> getMarketRateFromIndicator -> This could happen when there are still holes on trades and the process needs to catch up. ");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
try {
|
||||
candleArray = JSON.parse(text);
|
||||
|
||||
/* We need to find the candle at which the process is currently running. */
|
||||
|
||||
for (let i = 0; i < candleArray.length; i++) {
|
||||
|
||||
let candle = {
|
||||
open: candleArray[i][2],
|
||||
close: candleArray[i][3],
|
||||
min: candleArray[i][0],
|
||||
max: candleArray[i][1],
|
||||
begin: candleArray[i][4],
|
||||
end: candleArray[i][5]
|
||||
};
|
||||
|
||||
// TODO condition added for when there is no market rate available.
|
||||
if ((bot.processDatetime.valueOf() >= candle.begin && bot.processDatetime.valueOf() < candle.end)
|
||||
|| (i + 1) === candleArray.length) {
|
||||
|
||||
marketRate = (candle.open + candle.close) / 2;
|
||||
marketRate = thisObject.truncDecimals(marketRate);
|
||||
context.newHistoryRecord.marketRate = marketRate;
|
||||
|
||||
ticker = {
|
||||
bid: marketRate,
|
||||
ask: marketRate,
|
||||
last: marketRate
|
||||
};
|
||||
|
||||
validateExchangeSyncronicity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> onFileReceived -> err = " + JSON.stringify(err));
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry.");
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
}
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> onFileReceived -> err = " + JSON.stringify(err));
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function validateExchangeSyncronicity() {
|
||||
|
||||
try {
|
||||
@@ -345,22 +245,15 @@
|
||||
case "Live": {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> Live Mode Detected."); }
|
||||
exchangeAPI.getOpenPositions(bot.market, onResponse);
|
||||
exchangeAPI.getOpenOrders(bot.market, onResponse);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Backtest": {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> Backtest Mode Detected."); }
|
||||
let exchangePositions = []; // We simulate all positions were executed.
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, exchangePositions);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Competition": {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> Competition Mode Detected."); }
|
||||
exchangeAPI.getOpenPositions(bot.market, onResponse);
|
||||
let openOrders = []; // We simulate all positions were executed.
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, openOrders);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -372,15 +265,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onResponse(err, pExchangePositions) {
|
||||
function onResponse(err, pOpenOrders) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> onResponse -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> onResponse -> pExchangePositions = " + JSON.stringify(pExchangePositions)); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> onResponse -> pOpenOrders = " + JSON.stringify(pOpenOrders)); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: { // Everything went well, we have the information requested.
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getPositionsAtExchange -> onResponse -> Execution finished well."); }
|
||||
exchangePositions = pExchangePositions;
|
||||
openOrders = pOpenOrders;
|
||||
ordersExecutionCheck(callBack);
|
||||
return;
|
||||
}
|
||||
@@ -471,11 +364,11 @@
|
||||
let position = context.executionContext.positions[i];
|
||||
let exchangePosition;
|
||||
|
||||
for (let j = 0; j < exchangePositions.length; j++) {
|
||||
for (let j = 0; j < openOrders.length; j++) {
|
||||
|
||||
if (position.id === exchangePositions[j].id) {
|
||||
if (position.id === openOrders[j].id) {
|
||||
|
||||
exchangePosition = exchangePositions[j];
|
||||
exchangePosition = openOrders[j];
|
||||
positionFound();
|
||||
return;
|
||||
}
|
||||
@@ -525,12 +418,12 @@
|
||||
|
||||
}
|
||||
|
||||
function getPositionTradesAtExchange(pPositionId, innerCallBack) {
|
||||
function getPositionTradesAtExchange(pOrderId, innerCallBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> pPositionId = " + pPositionId); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> pOrderId = " + pOrderId); }
|
||||
|
||||
/*
|
||||
|
||||
@@ -543,7 +436,7 @@
|
||||
case "Live": {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> Live Mode Detected."); }
|
||||
exchangeAPI.getExecutedTrades(pPositionId, onResponse);
|
||||
exchangeAPI.getOrder(pOrderId, bot.market, onResponse);
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -558,25 +451,28 @@
|
||||
|
||||
for (let i = 0; i < context.executionContext.positions.length; i++) {
|
||||
|
||||
let thisPosition = context.executionContext.positions[i];
|
||||
let thisOrder = context.executionContext.positions[i];
|
||||
|
||||
if (thisPosition.id === pPositionId) {
|
||||
if (thisOrder.id === pOrderId) {
|
||||
|
||||
let feeRate = 0.002; // Default backtesting fee simulation
|
||||
|
||||
let trade = {
|
||||
id: Math.trunc(Math.random(1) * 1000000),
|
||||
type: thisPosition.type,
|
||||
rate: thisPosition.rate.toString(),
|
||||
amountA: thisObject.truncDecimals(thisPosition.amountA).toString(),
|
||||
amountB: thisObject.truncDecimals(thisPosition.amountB).toString(),
|
||||
type: thisOrder.type,
|
||||
rate: thisOrder.rate.toString(),
|
||||
amountA: thisObject.truncDecimals(thisOrder.amountA).toString(),
|
||||
amountB: thisObject.truncDecimals(thisOrder.amountB).toString(),
|
||||
fee: thisObject.truncDecimals(feeRate).toString(),
|
||||
date: (new Date()).valueOf()
|
||||
}
|
||||
|
||||
trades.push(trade);
|
||||
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, trades);
|
||||
let order = {
|
||||
trades: trades
|
||||
}
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, order);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -587,13 +483,6 @@
|
||||
return;
|
||||
}
|
||||
|
||||
case "Competition": {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> Competition Mode Detected."); }
|
||||
exchangeAPI.getExecutedTrades(pPositionId, onResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> Unexpected bot.startMode.");
|
||||
logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> bot.startMode = " + bot.startMode);
|
||||
@@ -602,7 +491,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onResponse(err, pTrades) {
|
||||
function onResponse(err, order) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> onResponse -> Entering function."); }
|
||||
@@ -610,7 +499,7 @@
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: { // Everything went well, we have the information requested.
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> onResponse -> Execution finished well."); }
|
||||
innerCallBack(pTrades);
|
||||
innerCallBack(order);
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
@@ -637,13 +526,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
function confirmOrderWasExecuted(pTrades) {
|
||||
function confirmOrderWasExecuted(order) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> pTrades = " + JSON.stringify(pTrades)); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> trades = " + JSON.stringify(trades)); }
|
||||
|
||||
let trades = order.trades
|
||||
/*
|
||||
|
||||
To confirm everything is ok, we will add all the amounts on trades asociated to the order and
|
||||
@@ -656,8 +546,8 @@
|
||||
let sumQuotedAsset = 0;
|
||||
let sumRate = 0;
|
||||
|
||||
for (let k = 0; k < pTrades.length; k++) {
|
||||
let trade = pTrades[k];
|
||||
for (let k = 0; k < trades.length; k++) {
|
||||
let trade = trades[k];
|
||||
sumBaseAsset = sumBaseAsset + thisObject.truncDecimals(trade.amountA);
|
||||
sumQuotedAsset = sumQuotedAsset + thisObject.truncDecimals(trade.amountB);
|
||||
sumRate = sumRate + thisObject.truncDecimals(trade.rate);
|
||||
@@ -686,12 +576,12 @@
|
||||
position.status = "executed";
|
||||
|
||||
if (position.type === "sell") {
|
||||
context.newHistoryRecord.sellExecRate = sumRate / pTrades.length;
|
||||
context.newHistoryRecord.sellExecRate = sumRate / trades.length;
|
||||
} else {
|
||||
context.newHistoryRecord.buyExecRate = sumRate / pTrades.length;
|
||||
context.newHistoryRecord.buyExecRate = sumRate / trades.length;
|
||||
}
|
||||
|
||||
applyTradesToContext(pTrades);
|
||||
applyTradesToContext(trades);
|
||||
|
||||
let newTransaction = {
|
||||
type: position.type + " executed",
|
||||
@@ -711,11 +601,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function confirmOrderWasPartiallyExecuted(pTrades) {
|
||||
function confirmOrderWasPartiallyExecuted(trades) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> Entering function."); }
|
||||
|
||||
let trades = order.trades
|
||||
|
||||
/*
|
||||
|
||||
To confirm everything is ok, we will add all the amounts on trades plus the remaining amounts
|
||||
@@ -727,8 +619,8 @@
|
||||
let sumBaseAsset = 0;
|
||||
let sumQuotedAsset = 0;
|
||||
|
||||
for (let k = 0; k < pTrades.length; k++) {
|
||||
let trade = pTrades[k];
|
||||
for (let k = 0; k < trades.length; k++) {
|
||||
let trade = trades[k];
|
||||
sumBaseAsset = sumBaseAsset + thisObject.truncDecimals(trade.amountA);
|
||||
sumQuotedAsset = sumQuotedAsset + thisObject.truncDecimals(trade.amountB);
|
||||
}
|
||||
@@ -777,7 +669,7 @@
|
||||
position.amountB = exchangePosition.amountB;
|
||||
position.date = (new Date(exchangePosition.date)).valueOf();
|
||||
|
||||
applyTradesToContext(pTrades);
|
||||
applyTradesToContext(trades);
|
||||
|
||||
let newTransaction = {
|
||||
type: position.type + " partially executed",
|
||||
@@ -797,7 +689,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function applyTradesToContext(pTrades) {
|
||||
function applyTradesToContext(trades) {
|
||||
|
||||
try {
|
||||
|
||||
@@ -805,9 +697,9 @@
|
||||
|
||||
/* Here we apply the trades that already happened at the exchange to the balance and available balance of the bot. We also calculate its profits. */
|
||||
|
||||
for (k = 0; k < pTrades.length; k++) {
|
||||
for (k = 0; k < trades.length; k++) {
|
||||
|
||||
let trade = pTrades[k];
|
||||
let trade = trades[k];
|
||||
|
||||
position.trades.push(trade);
|
||||
|
||||
@@ -917,10 +809,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
function putPosition(pType, pRate, pAmountA, pAmountB, callBackFunction) {
|
||||
function createOrder(pType, pRate, pAmountA, pAmountB, callBackFunction) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> Entering function."); }
|
||||
|
||||
/* Removing extra decimals. */
|
||||
|
||||
@@ -928,10 +820,10 @@
|
||||
pAmountA = thisObject.truncDecimals(pAmountA);
|
||||
pAmountB = thisObject.truncDecimals(pAmountB);
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pType = " + pType); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pRate = " + pRate); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountA = " + pAmountA); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountB = " + pAmountB); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> pType = " + pType); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> pRate = " + pRate); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> pAmountA = " + pAmountA); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> pAmountB = " + pAmountB); }
|
||||
|
||||
/* Validations that the limits are not surpassed. */
|
||||
|
||||
@@ -939,9 +831,9 @@
|
||||
|
||||
if (pAmountA > thisObject.truncDecimals(context.executionContext.availableBalance.baseAsset)) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountA is grater than the Available Balance.");
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountA = " + pAmountA);
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> Available Balance = " + thisObject.truncDecimals(context.executionContext.availableBalance.baseAsset));
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> pAmountA is grater than the Available Balance.");
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> pAmountA = " + pAmountA);
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> Available Balance = " + thisObject.truncDecimals(context.executionContext.availableBalance.baseAsset));
|
||||
|
||||
let err = {
|
||||
result: global.DEFAULT_FAIL_RESPONSE.result,
|
||||
@@ -957,9 +849,9 @@
|
||||
|
||||
if (pAmountB > thisObject.truncDecimals(context.executionContext.availableBalance.quotedAsset)) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountB is grater than the Available Balance.");
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountB = " + pAmountB);
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> Available Balance = " + thisObject.truncDecimals(context.executionContext.availableBalance.quotedAsset));
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> pAmountB is grater than the Available Balance.");
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> pAmountB = " + pAmountB);
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Input Validations -> Available Balance = " + thisObject.truncDecimals(context.executionContext.availableBalance.quotedAsset));
|
||||
|
||||
let err = {
|
||||
result: global.DEFAULT_FAIL_RESPONSE.result,
|
||||
@@ -977,7 +869,7 @@
|
||||
|
||||
case "Live": {
|
||||
|
||||
exchangeAPI.putPosition(bot.market, pType, pRate, pAmountA, pAmountB, onResponse);
|
||||
exchangeAPI.createOrder(bot.market, pType, pRate, pAmountA, pAmountB, onResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -985,43 +877,37 @@
|
||||
|
||||
if (pRate !== marketRate) {
|
||||
|
||||
logger.write(MODULE_NAME, "[WARNING] putPosition -> Input Validations -> putPosition Rate can is different to marketRate while in Backtesting Mode. ");
|
||||
logger.write(MODULE_NAME, "[WARNING] createOrder -> Input Validations -> createOrder Rate can is different to marketRate while in Backtesting Mode. ");
|
||||
//onResponse(global.DEFAULT_FAIL_RESPONSE, positionId);
|
||||
}
|
||||
|
||||
let positionId = Math.trunc(Math.random(1) * 1000000);
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> Simulating Exchange Response -> orderId = " + positionId); }
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, positionId);
|
||||
return;
|
||||
}
|
||||
|
||||
case "Competition": {
|
||||
|
||||
exchangeAPI.putPosition(bot.market, pType, pRate, pAmountA, pAmountB, onResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> Unexpected bot.startMode.");
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> bot.startMode = " + bot.startMode);
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> Unexpected bot.startMode.");
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> bot.startMode = " + bot.startMode);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function onResponse(err, pPositionId) {
|
||||
function onResponse(err, order) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> onResponse -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> onResponse -> pPositionId = " + pPositionId); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> onResponse -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> onResponse -> order.id = " + order.id); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: { // Everything went well, we have the information requested.
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> onResponse -> Execution finished well."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createOrder -> onResponse -> Execution finished well."); }
|
||||
|
||||
let position = {
|
||||
id: pPositionId,
|
||||
id: order.id,
|
||||
type: pType,
|
||||
rate: pRate,
|
||||
amountA: pAmountA,
|
||||
@@ -1063,149 +949,25 @@
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> onResponse -> Retry Later. Requesting Execution Retry.");
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> onResponse -> Retry Later. Requesting Execution Retry.");
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> onResponse -> Operation Failed. Aborting the process.");
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> onResponse -> Operation Failed. Aborting the process.");
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> onResponse -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> onResponse -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] putPosition -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function movePosition(pPosition, pNewRate, callBackFunction) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> pPosition = " + JSON.stringify(pPosition)); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> pNewRate = " + pNewRate); }
|
||||
|
||||
/* Removing extra decimals. */
|
||||
pNewRate = thisObject.truncDecimals(pNewRate);
|
||||
|
||||
let newAmountB;
|
||||
if (pPosition.type === "buy") {
|
||||
newAmountB = thisObject.truncDecimals(pPosition.amountA / pNewRate);
|
||||
} else {
|
||||
newAmountB = pPosition.amountB;
|
||||
}
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> newAmountB = " + newAmountB); }
|
||||
|
||||
switch (bot.startMode) {
|
||||
|
||||
case "Live": {
|
||||
|
||||
exchangeAPI.movePosition(pPosition, pNewRate, newAmountB, onResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
case "Backtest": {
|
||||
|
||||
let positionId = Math.trunc(Math.random(1) * 1000000);
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
|
||||
onResponse(global.DEFAULT_OK_RESPONSE, positionId);
|
||||
return;
|
||||
}
|
||||
|
||||
case "Competition": {
|
||||
|
||||
exchangeAPI.movePosition(pPosition, pNewRate, newAmountB, onResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> Unexpected bot.startMode.");
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> bot.startMode = " + bot.startMode);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function onResponse(err, pPositionId) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> onResponse -> Entering function."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> onResponse -> pPositionId = " + pPositionId); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: { // Everything went well, we have the information requested.
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> onResponse -> Execution finished well."); }
|
||||
|
||||
let newPosition = {
|
||||
id: pPositionId,
|
||||
type: pPosition.type,
|
||||
rate: pNewRate,
|
||||
amountA: pPosition.amountA,
|
||||
amountB: newAmountB,
|
||||
date: (bot.processDatetime.valueOf()),
|
||||
status: "open",
|
||||
trades: []
|
||||
};
|
||||
|
||||
let oldPosition = JSON.parse(JSON.stringify(pPosition));
|
||||
|
||||
/* We need to update the position we have on file. */
|
||||
|
||||
for (let i = 0; i < context.executionContext.positions.length; i++) {
|
||||
|
||||
if (context.executionContext.positions[i].id === pPosition.id) {
|
||||
|
||||
context.executionContext.positions[i] = newPosition;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let newTransaction = {
|
||||
type: "movePosition",
|
||||
oldPosition: oldPosition,
|
||||
newPosition: newPosition
|
||||
};
|
||||
|
||||
context.executionContext.transactions.push(newTransaction);
|
||||
|
||||
context.newHistoryRecord.movedPositions++;
|
||||
|
||||
recalculateRateAverages();
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, newPosition);
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> onResponse -> Retry Later. Requesting Execution Retry.");
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> onResponse -> Operation Failed. Aborting the process.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> onResponse -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] movePosition -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] createOrder -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
return
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.parentNode.dataBuilding === undefined) {
|
||||
logger.write(MODULE_NAME, "[WARN] start -> Product Definition without a Data Building Procedure. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
|
||||
logger.write(MODULE_NAME, "[WARN] start -> Product Definition " + outputDatasetNode.referenceParent.parentNode.name + " without a Data Building Procedure. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.code.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Dataset witn no codeName defined. Product Dataset = " + JSON.stringify(outputDatasetNode.referenceParent));
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
exports.newExchangeAPI = function newExchangeAPI(logger, BOT) {
|
||||
|
||||
let MODULE_NAME = "Exchange API";
|
||||
let LOG_INFO = true;
|
||||
let apiClient;
|
||||
let bot = BOT
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize,
|
||||
getTicker: getTicker,
|
||||
getOpenOrders: getOpenOrders,
|
||||
getOrder: getOrder,
|
||||
createOrder: createOrder,
|
||||
getMaxDecimalPositions: getMaxDecimalPositions
|
||||
};
|
||||
|
||||
let exchangeId
|
||||
let options = {}
|
||||
let exchange
|
||||
|
||||
const ccxt = require('ccxt')
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize(callBackFunction) {
|
||||
try {
|
||||
exchangeId = bot.exchange.toLowerCase()
|
||||
|
||||
let key = process.env.KEY
|
||||
let secret = process.env.SECRET
|
||||
|
||||
if (key === "undefined") { key = undefined }
|
||||
if (secret === "undefined") { secret = undefined }
|
||||
|
||||
const exchangeClass = ccxt[exchangeId]
|
||||
const exchangeConstructorParams = {
|
||||
'apiKey': key,
|
||||
'secret': secret,
|
||||
'timeout': 30000,
|
||||
'enableRateLimit': true,
|
||||
verbose: false,
|
||||
options: options
|
||||
}
|
||||
|
||||
exchange = new exchangeClass(exchangeConstructorParams)
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
logError("initialize -> err = " + err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function getMaxDecimalPositions() {
|
||||
return 8
|
||||
}
|
||||
|
||||
async function getTicker(market, callBackFunction) {
|
||||
try {
|
||||
logInfo("getTicker -> Entering function.");
|
||||
const symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let ticker
|
||||
|
||||
if (exchange.has['fetchTicker']) {
|
||||
ticker = await (exchange.fetchTicker(symbol))
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, ticker)
|
||||
} else {
|
||||
logError("getTicker -> Exchange does not support fetchTicker command.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logError("getTicker -> err = " + err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
async function getOpenOrders(market, callBackFunction) {
|
||||
try {
|
||||
logInfo("getOpenOrders -> Entering function. market = " + JSON.stringify(market));
|
||||
|
||||
const symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let openOrders
|
||||
|
||||
if (exchange.has['fetchOpenOrders']) {
|
||||
openOrders = await(exchange.fetchOpenOrders (symbol))
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, openOrders)
|
||||
} else {
|
||||
logError("getOpenOrders -> Exchange does not support fetchOpenOrders command.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logError("getOpenOrders -> Error = " + err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
async function getOrder(orderId, market, callBackFunction) {
|
||||
try {
|
||||
logInfo("getOrder -> Entering function. orderId = " + orderId);
|
||||
|
||||
const symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let order
|
||||
|
||||
if (exchange.has['fetchOrder']) {
|
||||
order = await (exchange.fetchOrder(orderId, symbol))
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, order)
|
||||
} else {
|
||||
logError("getOrder -> Exchange does not support fetchOrder command.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
} catch (err) {
|
||||
logError("getOrder -> Error = " + err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
async function createOrder(market, side, price, cost, amount, callBackFunction) {
|
||||
try {
|
||||
logInfo("createOrder -> Entering function.");
|
||||
|
||||
const symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
|
||||
logInfo("createOrder -> market = " + market.assetA + "_" + market.assetB);
|
||||
logInfo("createOrder -> side = " + side);
|
||||
logInfo("createOrder -> cost = " + cost);
|
||||
logInfo("createOrder -> amount = " + amount);
|
||||
logInfo("createOrder -> price = " + price);
|
||||
|
||||
if (side !== "buy" && side !== "sell") {
|
||||
logError("createOrder -> side must be either 'buy' or 'sell'.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
|
||||
let type = 'market'
|
||||
let order
|
||||
|
||||
if (exchange.has['createOrder']) {
|
||||
order = await(exchange.createOrder(symbol, type, side, amount))
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, order)
|
||||
} else {
|
||||
logError("createOrder -> Exchange does not support createOrder command.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logError("createOrder -> err = " + JSON.stringify(err.stack) || err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function logInfo(message) {
|
||||
if (LOG_INFO === true) { logger.write(MODULE_NAME, '[INFO] ' + message) }
|
||||
}
|
||||
|
||||
function logError(message) {
|
||||
logger.write(MODULE_NAME, '[ERROR] ' + message)
|
||||
}
|
||||
};
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, pAssistant, callBackFunction) {
|
||||
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, exchangeAPI, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
let USER_BOT_MODULE = require("./TradingBot")
|
||||
|
||||
botInstance = USER_BOT_MODULE.newTradingBot(bot, logger, UTILITIES, FILE_STORAGE);
|
||||
botInstance.initialize(pAssistant, callBackFunction);
|
||||
botInstance.initialize(exchangeAPI, callBackFunction);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
|
||||
+25
-15
@@ -2,6 +2,7 @@
|
||||
|
||||
const MODULE_NAME = "Session"
|
||||
const FULL_LOG = true;
|
||||
const ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize
|
||||
@@ -97,6 +98,17 @@
|
||||
bot.STOP_SESSION = true
|
||||
}
|
||||
|
||||
function checkDatetimes() {
|
||||
if (bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf() < (new Date()).valueOf()) {
|
||||
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> startLiveTrading -> Overriding initialDatetime with present datetime because " + bot.VALUES_TO_USE.timeRange.initialDatetime + " is in the past."); }
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date()
|
||||
}
|
||||
if (bot.VALUES_TO_USE.timeRange.finalDatetime.valueOf() < (new Date()).valueOf()) {
|
||||
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> startLiveTrading -> Overriding finalDatetime with present datetime plus one year because " + bot.VALUES_TO_USE.timeRange.finalDatetime + " is in the past."); }
|
||||
bot.VALUES_TO_USE.timeRange.finalDatetime = new Date() + ONE_YEAR_IN_MILISECONDS
|
||||
}
|
||||
}
|
||||
|
||||
function startBackTesting(message) {
|
||||
bot.startMode = "Backtest"
|
||||
if (bot.VALUES_TO_USE.timeRange.finalDatetime.valueOf() > (new Date()).valueOf()) {
|
||||
@@ -117,9 +129,7 @@
|
||||
}
|
||||
|
||||
bot.startMode = "Live"
|
||||
if (bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf() < (new Date()).valueOf()) {
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date()
|
||||
}
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
@@ -135,9 +145,7 @@
|
||||
}
|
||||
|
||||
bot.startMode = "Live"
|
||||
if (bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf() < (new Date()).valueOf()) {
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date()
|
||||
}
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
@@ -164,9 +172,7 @@
|
||||
function startPaperTrading(message) {
|
||||
bot.startMode = "Backtest"
|
||||
|
||||
if (bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf() < (new Date()).valueOf()) {
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date()
|
||||
}
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.hasTheBotJustStarted = true
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
@@ -204,7 +210,7 @@
|
||||
}
|
||||
|
||||
/* Session Type Dependant Default Values */
|
||||
const ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000
|
||||
|
||||
switch (bot.SESSION.type) {
|
||||
case 'Backtesting Session': {
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date((new Date()).valueOf() - ONE_YEAR_IN_MILISECONDS)
|
||||
@@ -247,7 +253,9 @@
|
||||
bot.VALUES_TO_USE.baseAsset = code.codeName;
|
||||
}
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
code = tradingSystem.parameters.baseAsset.code
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (code.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceA = code.initialBalance;
|
||||
bot.VALUES_TO_USE.initialBalanceB = 0
|
||||
@@ -347,16 +355,18 @@
|
||||
/* Base Asset and Initial Balances. */
|
||||
{
|
||||
if (bot.SESSION.parameters.baseAsset !== undefined) {
|
||||
if (tradingSystem.parameters.baseAsset.referenceParent !== undefined) {
|
||||
if (tradingSystem.parameters.baseAsset.referenceParent.referenceParent !== undefined) {
|
||||
if (bot.SESSION.parameters.baseAsset.referenceParent !== undefined) {
|
||||
if (bot.SESSION.parameters.baseAsset.referenceParent.referenceParent !== undefined) {
|
||||
|
||||
let code = tradingSystem.parameters.baseAsset.referenceParent.referenceParent.code
|
||||
let code = bot.SESSION.parameters.baseAsset.referenceParent.referenceParent.code
|
||||
|
||||
if (code.codeName !== undefined) {
|
||||
bot.VALUES_TO_USE.baseAsset = code.codeName;
|
||||
}
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
code = bot.SESSION.parameters.baseAsset.code
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (code.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceA = code.initialBalance;
|
||||
bot.VALUES_TO_USE.initialBalanceB = 0
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
const COMMONS = require('./Commons.js');
|
||||
let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE);
|
||||
|
||||
let assistant;
|
||||
let exchangeAPI;
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
commons = undefined
|
||||
}
|
||||
|
||||
function initialize(pAssistant, callBackFunction) {
|
||||
function initialize(pExchangeAPI, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
|
||||
|
||||
assistant = pAssistant;
|
||||
exchangeAPI = pExchangeAPI;
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
@@ -130,7 +130,7 @@
|
||||
timeFrameLabel,
|
||||
currentDay,
|
||||
interExecutionMemory,
|
||||
assistant,
|
||||
exchangeAPI,
|
||||
writeFiles,
|
||||
callBackFunction)
|
||||
|
||||
|
||||
@@ -145,9 +145,7 @@
|
||||
/* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */
|
||||
|
||||
const UTILITIES = require(ROOT_DIR + 'CloudUtilities');
|
||||
const EXCHANGE_API = require('@superalgos/exchange-gateway');
|
||||
const CONTEXT = require(ROOT_DIR + 'Context');
|
||||
const ASSISTANT = require(ROOT_DIR + 'Assistant');
|
||||
const EXCHANGE_API = require(ROOT_DIR + 'ExchangeAPI');
|
||||
const STATUS_REPORT = require(ROOT_DIR + 'StatusReport');
|
||||
const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies');
|
||||
const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies');
|
||||
@@ -443,7 +441,7 @@
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); }
|
||||
initializeContext();
|
||||
initializeExchangeAPI();
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
@@ -500,88 +498,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function initializeContext() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeContext -> Entering function."); }
|
||||
|
||||
context = CONTEXT.newContext(bot, logger, UTILITIES);
|
||||
context.initialize(statusDependencies, onInizialized);
|
||||
|
||||
function onInizialized(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeContext -> onInizialized -> Entering function."); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeContext -> onInizialized -> Execution finished well."); }
|
||||
initializeExchangeAPI();
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeContext -> onInizialized -> Retry Later. Requesting Execution Retry.");
|
||||
nextWaitTime = 'Retry';
|
||||
loopControl(nextWaitTime);
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
sessionStopped()
|
||||
processStopped()
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> Operation Failed. Aborting the process.");
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
|
||||
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeExchangeAPI() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); }
|
||||
|
||||
exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, bot.exchange);
|
||||
exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, bot);
|
||||
|
||||
exchangeAPI.initialize(onInizialized);
|
||||
|
||||
@@ -594,7 +517,25 @@
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> onInizialized -> Execution finished well."); }
|
||||
initializeAssistant();
|
||||
|
||||
switch (processConfig.framework.name) {
|
||||
case 'Multi-Period': {
|
||||
processFramework = MULTI_PERIOD.newMultiPeriod(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS);
|
||||
intitializeProcessFramework();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> onInizialized -> Process Framework not Supported.");
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> onInizialized -> Process Framework Name = " + processConfig.framework.name);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
@@ -651,112 +592,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function initializeAssistant() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeAssistant -> Entering function."); }
|
||||
|
||||
assistant = ASSISTANT.newAssistant(bot, logger, UTILITIES);
|
||||
assistant.initialize(context, exchangeAPI, dataDependencies, onInizialized);
|
||||
|
||||
function onInizialized(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeAssistant -> onInizialized -> Entering function."); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeAssistant -> onInizialized -> Execution finished well."); }
|
||||
|
||||
/* If the process is configured to run inside a framework, we continue there, otherwise we run the bot directly. */
|
||||
if (processConfig.framework === undefined) {
|
||||
initializeUserBot();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (processConfig.framework.name) {
|
||||
case 'Multi-Period': {
|
||||
processFramework = MULTI_PERIOD.newMultiPeriod(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS);
|
||||
intitializeProcessFramework();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> Process Framework not Supported.");
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> Process Framework Name = " + processConfig.framework.name);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeAssistant -> onInizialized -> Retry Later. Requesting Execution Retry.");
|
||||
nextWaitTime = 'Retry';
|
||||
loopControl(nextWaitTime);
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
sessionStopped()
|
||||
processStopped()
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> Operation Failed. Aborting the process.");
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
|
||||
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
function intitializeProcessFramework() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); }
|
||||
|
||||
processFramework.initialize(processConfig, statusDependencies, dataDependencies, assistant, onInizialized);
|
||||
processFramework.initialize(processConfig, statusDependencies, dataDependencies, exchangeAPI, onInizialized);
|
||||
|
||||
function onInizialized(err) {
|
||||
|
||||
@@ -859,7 +701,7 @@
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well.");
|
||||
nextWaitTime = 'Normal';
|
||||
saveContext();
|
||||
raiseEventsProcessOutput()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
@@ -943,84 +785,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function saveContext() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Entering function."); }
|
||||
|
||||
context.saveThemAll(onFinished);
|
||||
|
||||
function onFinished(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> onFinished -> Entering function."); }
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> onFinished -> Execution finished well."); }
|
||||
raiseEventsProcessOutput()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> Can not retry at this point.");
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
sessionStopped()
|
||||
processStopped()
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> Operation Failed. Aborting the process.");
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> Unhandled err.result received. -> err = " + err.message);
|
||||
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> err = "+ err.stack);
|
||||
logger.persist();
|
||||
clearInterval(fixedTimeLoopIntervalHandle);
|
||||
clearTimeout(nextLoopTimeoutHandle);
|
||||
clearTimeout(checkLoopHealthHandle);
|
||||
bot.enableCheckLoopHealth = false;
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
function raiseEventsProcessOutput() {
|
||||
|
||||
try {
|
||||
|
||||
+98
-155
@@ -39,7 +39,7 @@
|
||||
timeFrameLabel,
|
||||
currentDay,
|
||||
interExecutionMemory,
|
||||
assistant,
|
||||
exchangeAPI,
|
||||
callback,
|
||||
callBackFunction) {
|
||||
|
||||
@@ -167,6 +167,8 @@
|
||||
let periods = 0;
|
||||
let positionPeriods = 0;
|
||||
|
||||
let closeRate
|
||||
|
||||
/* Usefull counters for conditions and formulas */
|
||||
|
||||
let distanceToLast = {
|
||||
@@ -554,8 +556,6 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Candle Begin @ " + (new Date(candle.begin)).toLocaleString()) }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Candle End @ " + (new Date(candle.end)).toLocaleString()) }
|
||||
|
||||
/* Assistant Info */
|
||||
|
||||
let ticker = {
|
||||
bid: candle.close,
|
||||
ask: candle.close,
|
||||
@@ -706,7 +706,7 @@
|
||||
if (openStage !== undefined) {
|
||||
|
||||
/* Default Values*/
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
positionSize = balanceBaseAsset;
|
||||
positionRate = candle.close;
|
||||
} else {
|
||||
@@ -729,13 +729,13 @@
|
||||
initialDefinition.positionSize.formula.error = err.message
|
||||
}
|
||||
if (isNaN(positionSize)) {
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
positionSize = balanceBaseAsset;
|
||||
} else {
|
||||
positionSize = balanceQuotedAsset;
|
||||
}
|
||||
} else {
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (positionSize > balanceBaseAsset) { positionSize = balanceBaseAsset }
|
||||
} else {
|
||||
if (positionSize > balanceQuotedAsset) { positionSize = balanceQuotedAsset }
|
||||
@@ -756,7 +756,7 @@
|
||||
initialDefinition.positionRate.formula.error = err.message
|
||||
}
|
||||
if (isNaN(positionRate)) {
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
positionRate = candle.close;
|
||||
} else {
|
||||
positionRate = candle.close;
|
||||
@@ -1093,7 +1093,7 @@
|
||||
let maximumBalance
|
||||
let balance
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
balance = balanceBaseAsset
|
||||
minimumBalance = bot.VALUES_TO_USE.minimumBalanceA
|
||||
maximumBalance = bot.VALUES_TO_USE.maximumBalanceA
|
||||
@@ -1675,7 +1675,7 @@
|
||||
|
||||
/* Stop Loss condition: Here we verify if the Stop Loss was hitted or not. */
|
||||
|
||||
if ((bot.VALUES_TO_USE.baseAsset === 'BTC' && candle.max >= stopLoss) || (bot.VALUES_TO_USE.baseAsset !== 'BTC' && candle.min <= stopLoss)) {
|
||||
if ((bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset && candle.max >= stopLoss) || (bot.VALUES_TO_USE.baseAsset !== bot.market.baseAsset && candle.min <= stopLoss)) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Stop Loss was hit."); }
|
||||
/*
|
||||
@@ -1685,7 +1685,7 @@
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (stopLoss < candle.min) {
|
||||
stopLoss = candle.min
|
||||
if (processingDailyFiles) {
|
||||
@@ -1710,42 +1710,15 @@
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedStopLoss * bot.VALUES_TO_USE.slippage.stopLoss / 100
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
slippedStopLoss = slippedStopLoss + slippageAmount
|
||||
} else {
|
||||
slippedStopLoss = slippedStopLoss - slippageAmount
|
||||
}
|
||||
|
||||
let finalStopLoss = slippedStopLoss;
|
||||
closeRate = slippedStopLoss;
|
||||
|
||||
let feePaid = 0
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
strategy.positionSize = balanceQuotedAsset / finalStopLoss;
|
||||
strategy.positionRate = finalStopLoss;
|
||||
|
||||
feePaid = balanceQuotedAsset / finalStopLoss * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceBaseAsset = balanceBaseAsset + balanceQuotedAsset / finalStopLoss - feePaid;
|
||||
balanceQuotedAsset = 0;
|
||||
} else {
|
||||
strategy.positionSize = balanceBaseAsset * finalStopLoss;
|
||||
strategy.positionRate = finalStopLoss;
|
||||
|
||||
feePaid = balanceBaseAsset * finalStopLoss * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceQuotedAsset = balanceQuotedAsset + balanceBaseAsset * finalStopLoss - feePaid;
|
||||
balanceBaseAsset = 0;
|
||||
}
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
yesterday.balanceBaseAsset = balanceBaseAsset;
|
||||
yesterday.balanceQuotedAsset = balanceQuotedAsset;
|
||||
}
|
||||
}
|
||||
|
||||
marketRate = finalStopLoss;
|
||||
marketRate = closeRate;
|
||||
type = '"Close@StopLoss"';
|
||||
strategyStage = 'Close Stage';
|
||||
stopLossStage = 'No Stage';
|
||||
@@ -1753,7 +1726,7 @@
|
||||
currentTrade.end = candle.end;
|
||||
currentTrade.status = 1;
|
||||
currentTrade.exitType = 1;
|
||||
currentTrade.endRate = finalStopLoss;
|
||||
currentTrade.endRate = closeRate;
|
||||
|
||||
closePositionNow = true;
|
||||
|
||||
@@ -1772,7 +1745,7 @@
|
||||
|
||||
/* Take Profit condition: Here we verify if the Take Profit was hit or not. */
|
||||
|
||||
if ((bot.VALUES_TO_USE.baseAsset === 'BTC' && candle.min <= takeProfit) || (bot.VALUES_TO_USE.baseAsset !== 'BTC' && candle.max >= takeProfit)) {
|
||||
if ((bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset && candle.min <= takeProfit) || (bot.VALUES_TO_USE.baseAsset !== bot.market.baseAsset && candle.max >= takeProfit)) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Take Profit was hit."); }
|
||||
/*
|
||||
@@ -1782,7 +1755,7 @@
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (takeProfit > candle.max) {
|
||||
takeProfit = candle.max
|
||||
if (processingDailyFiles) {
|
||||
@@ -1806,43 +1779,15 @@
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedTakeProfit * bot.VALUES_TO_USE.slippage.takeProfit / 100
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
slippedTakeProfit = slippedTakeProfit + slippageAmount
|
||||
} else {
|
||||
slippedTakeProfit = slippedTakeProfit - slippageAmount
|
||||
}
|
||||
|
||||
let finalTakeProfit = slippedTakeProfit;
|
||||
closeRate = slippedTakeProfit;
|
||||
|
||||
let feePaid = 0
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
strategy.positionSize = balanceQuotedAsset / finalTakeProfit;
|
||||
strategy.positionRate = finalTakeProfit;
|
||||
|
||||
feePaid = balanceQuotedAsset / finalTakeProfit * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceBaseAsset = balanceBaseAsset + balanceQuotedAsset / finalTakeProfit - feePaid;
|
||||
balanceQuotedAsset = 0;
|
||||
} else {
|
||||
strategy.positionSize = balanceBaseAsset * finalTakeProfit;
|
||||
strategy.positionRate = finalTakeProfit;
|
||||
|
||||
feePaid = balanceBaseAsset * finalTakeProfit * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceQuotedAsset = balanceQuotedAsset + balanceBaseAsset * finalTakeProfit - feePaid;
|
||||
balanceBaseAsset = 0;
|
||||
}
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
yesterday.balanceBaseAsset = balanceBaseAsset;
|
||||
yesterday.balanceQuotedAsset = balanceQuotedAsset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
marketRate = finalTakeProfit;
|
||||
marketRate = closeRate;
|
||||
type = '"Close@TakeProfit"';
|
||||
strategyStage = 'Close Stage';
|
||||
stopLossStage = 'No Stage';
|
||||
@@ -1851,7 +1796,7 @@
|
||||
currentTrade.end = candle.end;
|
||||
currentTrade.status = 1;
|
||||
currentTrade.exitType = 2;
|
||||
currentTrade.endRate = finalTakeProfit;
|
||||
currentTrade.endRate = closeRate;
|
||||
|
||||
closePositionNow = true;
|
||||
|
||||
@@ -1895,7 +1840,7 @@
|
||||
/* We take what was calculated at the formula and apply the slippage. */
|
||||
let slippageAmount = tradePositionRate * bot.VALUES_TO_USE.slippage.positionRate / 100
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
tradePositionRate = tradePositionRate - slippageAmount
|
||||
} else {
|
||||
tradePositionRate = tradePositionRate + slippageAmount
|
||||
@@ -1993,20 +1938,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Checking the status of current positions */
|
||||
let positions = assistant.getPositions();
|
||||
if (positions.length > 0) {
|
||||
let position = positions[positions.length - 1] // We are allways checking the the last position is not open.
|
||||
if (position.status === 'open') {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because the last position is still open. "); }
|
||||
afterLoop();
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */
|
||||
|
||||
if (interExecutionMemory.executionContext !== undefined) {
|
||||
if (interExecutionMemory.executionContext.periods !== undefined) {
|
||||
if (periods <= interExecutionMemory.executionContext.periods) {
|
||||
@@ -2030,34 +1962,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
let openPositionRate
|
||||
let orderPrice
|
||||
let amountA
|
||||
let amountB
|
||||
let positionDirection
|
||||
let availableBalance = assistant.getAvailableBalance()
|
||||
let orderSide
|
||||
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
positionDirection = "sell"
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
orderSide = "sell"
|
||||
|
||||
openPositionRate = tradePositionRate - 100 // 100 is Provisional since we do have management of orders yet
|
||||
orderPrice = tradePositionRate - 100 // This is going to be ingnored at the Exchange API for now since we only put market orders.
|
||||
|
||||
amountA = tradePositionSize * openPositionRate
|
||||
amountA = tradePositionSize * orderPrice
|
||||
amountB = tradePositionSize
|
||||
|
||||
if (amountB > availableBalance.quotedAsset) { // The assistant know what fees were paid.
|
||||
amountB = availableBalance.quotedAsset
|
||||
}
|
||||
|
||||
} else {
|
||||
positionDirection = "buy"
|
||||
orderSide = "buy"
|
||||
|
||||
openPositionRate = tradePositionRate + 100 // 100 is Provisional since we do have management of orders yet
|
||||
orderPrice = tradePositionRate // This is going to be ingnored at the Exchange API for now since we only put market orders.
|
||||
|
||||
amountA = tradePositionSize
|
||||
amountB = tradePositionSize / openPositionRate
|
||||
amountB = tradePositionSize / orderPrice
|
||||
|
||||
if (amountA > availableBalance.baseAsset) { // The assistant know what fees were paid.
|
||||
amountA = availableBalance.baseAsset
|
||||
}
|
||||
}
|
||||
|
||||
interExecutionMemory.executionContext = {
|
||||
@@ -2065,46 +1991,47 @@
|
||||
periods: periods,
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Ready to put order."); }
|
||||
assistant.putPosition(positionDirection, openPositionRate, amountA, amountB, onOrderPut)
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Ready to create order."); }
|
||||
exchangeAPI.createOrder(bot.market, orderSide, orderPrice, amountA, amountB, onOrderCreated)
|
||||
|
||||
function onOrderPut(err) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Entering function."); }
|
||||
function onOrderCreated(err, order) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> Entering function."); }
|
||||
|
||||
try {
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> DEFAULT_OK_RESPONSE "); }
|
||||
interExecutionMemory.executionContext = {
|
||||
status: "In a Position",
|
||||
periods: periods,
|
||||
amountA: amountA,
|
||||
amountB: amountB
|
||||
amountB: amountB,
|
||||
orderId: order.id
|
||||
}
|
||||
takePositionAtSimulation()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Message = " + err.message); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> DEFAULT_FAIL_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> Message = " + err.message); }
|
||||
strategy.openStage.openExecution.error = err.message
|
||||
afterLoop()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Message = " + err.message); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> DEFAULT_RETRY_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> Message = " + err.message); }
|
||||
strategy.openStage.openExecution.error = err.message
|
||||
afterLoop()
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> Unexpected Response -> Message = " + err.message); }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -2135,7 +2062,7 @@
|
||||
|
||||
let feePaid = 0
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
|
||||
feePaid = tradePositionSize * tradePositionRate * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
@@ -2231,19 +2158,7 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Entering function."); }
|
||||
|
||||
/* Checking the status of current positions */
|
||||
let positions = assistant.getPositions();
|
||||
if (positions.length > 0) {
|
||||
let position = positions[positions.length - 1] // We are allways checking the the last position is not open.
|
||||
if (position.status === 'open') {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> Exiting function because status of last position is Open."); }
|
||||
afterLoop();
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */
|
||||
|
||||
if (interExecutionMemory.executionContext !== undefined) {
|
||||
if (interExecutionMemory.executionContext.periods !== undefined) {
|
||||
if (periods <= interExecutionMemory.executionContext.periods) {
|
||||
@@ -2254,27 +2169,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
let closePositionRate
|
||||
let orderPrice
|
||||
let amountA
|
||||
let amountB
|
||||
let positionDirection
|
||||
let availableBalance = assistant.getAvailableBalance()
|
||||
let orderSide
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
positionDirection = "buy"
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
orderSide = "buy"
|
||||
|
||||
closePositionRate = ticker.last + 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff.
|
||||
orderPrice = ticker.last + 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff.
|
||||
|
||||
amountA = availableBalance.baseAsset
|
||||
amountB = availableBalance.baseAsset / closePositionRate
|
||||
amountA = balanceQuotedAsset
|
||||
amountB = balanceQuotedAsset / orderPrice
|
||||
|
||||
} else {
|
||||
positionDirection = "sell"
|
||||
orderSide = "sell"
|
||||
|
||||
closePositionRate = ticker.last - 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff.
|
||||
orderPrice = ticker.last - 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff.
|
||||
|
||||
amountA = availableBalance.quotedAsset * closePositionRate
|
||||
amountB = availableBalance.quotedAsset
|
||||
amountA = balanceBaseAsset * orderPrice
|
||||
amountB = balanceBaseAsset
|
||||
|
||||
}
|
||||
|
||||
@@ -2284,44 +2198,45 @@
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> About to close position at the exchange."); }
|
||||
assistant.putPosition(positionDirection, closePositionRate, amountA, amountB, onOrderPut)
|
||||
exchangeAPI.createOrder(bot.market, orderSide, orderPrice, amountA, amountB, onOrderCreated)
|
||||
|
||||
function onOrderPut(err) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> Entering function."); }
|
||||
function onOrderCreated(err, order) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> Entering function."); }
|
||||
|
||||
try {
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> DEFAULT_OK_RESPONSE "); }
|
||||
interExecutionMemory.executionContext = {
|
||||
status: "Position Closed",
|
||||
periods: periods,
|
||||
amountA: amountA,
|
||||
amountB: amountB
|
||||
amountB: amountB,
|
||||
orderId: order.id
|
||||
}
|
||||
closePositionAtSimulation()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> DEFAULT_FAIL_RESPONSE "); }
|
||||
/* We will assume that the problem is temporary, and expect that it will work at the next execution.*/
|
||||
strategy.closeStage.closeExecution.error = err.message
|
||||
afterLoop()
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_RETRY_RESPONSE.result: {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> DEFAULT_RETRY_RESPONSE "); }
|
||||
strategy.closeStage.closeExecution.error = err.message
|
||||
afterLoop()
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> Unexpected Response -> Message = " + err.message); }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderPut -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -2339,7 +2254,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
let feePaid = 0
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
strategy.positionSize = balanceQuotedAsset / closeRate;
|
||||
strategy.positionRate = closeRate;
|
||||
|
||||
feePaid = balanceQuotedAsset / closeRate * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceBaseAsset = balanceBaseAsset + balanceQuotedAsset / closeRate - feePaid;
|
||||
balanceQuotedAsset = 0;
|
||||
} else {
|
||||
strategy.positionSize = balanceBaseAsset * closeRate;
|
||||
strategy.positionRate = closeRate;
|
||||
|
||||
feePaid = balanceBaseAsset * closeRate * bot.VALUES_TO_USE.feeStructure.taker / 100
|
||||
|
||||
balanceQuotedAsset = balanceQuotedAsset + balanceBaseAsset * closeRate - feePaid;
|
||||
balanceBaseAsset = 0;
|
||||
}
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
yesterday.balanceBaseAsset = balanceBaseAsset;
|
||||
yesterday.balanceQuotedAsset = balanceQuotedAsset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
lastTradeProfitLoss = balanceBaseAsset - previousBalanceBaseAsset;
|
||||
lastTradeROI = lastTradeProfitLoss * 100 / tradePositionSize;
|
||||
if (isNaN(lastTradeROI)) { lastTradeROI = 0; }
|
||||
@@ -2386,7 +2329,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
ROI = (bot.VALUES_TO_USE.initialBalanceA + profit) / bot.VALUES_TO_USE.initialBalanceA - 1;
|
||||
hitRatio = hits / roundtrips;
|
||||
anualizedRateOfReturn = ROI / days * 365;
|
||||
@@ -2652,7 +2595,7 @@
|
||||
currentTrade.endRate = candle.close
|
||||
|
||||
/* Here we will calculate the ongoing ROI */
|
||||
if (bot.VALUES_TO_USE.baseAsset === 'BTC') {
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
currentTrade.lastTradeROI = (tradePositionRate - candle.close) / tradePositionRate * 100
|
||||
} else {
|
||||
currentTrade.lastTradeROI = (candle.close - tradePositionRate) / tradePositionRate * 100
|
||||
|
||||
Generated
+2
-738
@@ -1,212 +1,19 @@
|
||||
{
|
||||
"name": "@superalgos/clone-executor",
|
||||
"version": "1.0.51",
|
||||
"name": "@superalgos/taskserver",
|
||||
"version": "2.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@superalgos/exchange-gateway": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@superalgos/exchange-gateway/-/exchange-gateway-0.0.10.tgz",
|
||||
"integrity": "sha512-VsiGeEyqD7NXvn2tFoqqz036WRBtzy6HvpbXqhl/+xG4SMbo2w9hb6AdAeH4KxuU2S7l/oO8zI9d15f30Q191Q==",
|
||||
"requires": {
|
||||
"axios": "0.19.0",
|
||||
"dotenv": "8.0.0",
|
||||
"nonce": "1.0.4",
|
||||
"querystring": "0.2.0",
|
||||
"request": "2.88.0",
|
||||
"retry": "0.12.0",
|
||||
"superagent": "5.1.0",
|
||||
"underscore": "1.9.1"
|
||||
}
|
||||
},
|
||||
"@superalgos/mqservice": {
|
||||
"version": "0.0.17",
|
||||
"resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.17.tgz",
|
||||
"integrity": "sha512-mxg2AtfFJ78n/p+JK/o6nTrnR+ZPlBNcq7k+6Epnl1t63ldrcm98WOgIQZaNezPPf0E7gSjVX3p+uZO1Ass0kA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.7.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz",
|
||||
"integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "2.0.1",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.4.1",
|
||||
"uri-js": "4.2.2"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "2.1.2"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
|
||||
"integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
|
||||
"requires": {
|
||||
"lodash": "4.17.11"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
|
||||
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
|
||||
"requires": {
|
||||
"follow-redirects": "1.5.10",
|
||||
"is-buffer": "2.0.3"
|
||||
}
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"ccxt": {
|
||||
"version": "1.21.82",
|
||||
"resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.21.82.tgz",
|
||||
"integrity": "sha512-+HX/6WK8BM5c9OwhALl9zzMKvueZfHDXVmfrKNmQ4005hc+BtNuNe47XEs6dAylY+ll7n9JpzaoIZhy6Lipiew=="
|
||||
},
|
||||
"color": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
|
||||
"integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
|
||||
"requires": {
|
||||
"color-convert": "1.9.3",
|
||||
"color-string": "1.5.3"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
|
||||
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3",
|
||||
"simple-swizzle": "0.2.2"
|
||||
}
|
||||
},
|
||||
"colornames": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
|
||||
"integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
|
||||
"integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
|
||||
},
|
||||
"colorspace": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
|
||||
"integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
|
||||
"requires": {
|
||||
"color": "3.0.0",
|
||||
"text-hex": "1.0.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "1.0.0"
|
||||
}
|
||||
},
|
||||
"component-emitter": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
|
||||
},
|
||||
"cookiejar": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
|
||||
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"diagnostics": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
|
||||
"integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
|
||||
"requires": {
|
||||
"colorspace": "1.1.2",
|
||||
"enabled": "1.0.2",
|
||||
"kuler": "1.0.1"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz",
|
||||
@@ -217,153 +24,11 @@
|
||||
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz",
|
||||
"integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "0.1.1",
|
||||
"safer-buffer": "2.1.2"
|
||||
}
|
||||
},
|
||||
"enabled": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
|
||||
"integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
|
||||
"requires": {
|
||||
"env-variable": "0.0.5"
|
||||
}
|
||||
},
|
||||
"env-variable": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
|
||||
"integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA=="
|
||||
},
|
||||
"event-pubsub": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
|
||||
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
|
||||
"integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
|
||||
},
|
||||
"fecha": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
|
||||
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
|
||||
"requires": {
|
||||
"debug": "3.1.0"
|
||||
}
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "0.4.0",
|
||||
"combined-stream": "1.0.8",
|
||||
"mime-types": "2.1.24"
|
||||
}
|
||||
},
|
||||
"formidable": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
|
||||
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"requires": {
|
||||
"ajv": "6.10.2",
|
||||
"har-schema": "2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"jsprim": "1.4.1",
|
||||
"sshpk": "1.16.1"
|
||||
}
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
},
|
||||
"is-buffer": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
|
||||
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"js-message": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
||||
@@ -377,97 +42,6 @@
|
||||
"easy-stack": "1.0.0"
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"kuler": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
|
||||
"integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
|
||||
"requires": {
|
||||
"colornames": "1.1.1"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"logform": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz",
|
||||
"integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==",
|
||||
"requires": {
|
||||
"colors": "1.3.3",
|
||||
"fast-safe-stringify": "2.0.6",
|
||||
"fecha": "2.3.3",
|
||||
"ms": "2.1.1",
|
||||
"triple-beam": "1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.40.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
||||
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.24",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
||||
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.40.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
@@ -483,195 +57,11 @@
|
||||
"js-queue": "2.0.0"
|
||||
}
|
||||
},
|
||||
"nonce": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/nonce/-/nonce-1.0.4.tgz",
|
||||
"integrity": "sha1-7nMCrejBvvR28wG4yR9cxRpIdhI="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"one-time": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
|
||||
"integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
|
||||
"integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
|
||||
"integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
|
||||
"requires": {
|
||||
"inherits": "2.0.3",
|
||||
"string_decoder": "1.2.0",
|
||||
"util-deprecate": "1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"requires": {
|
||||
"aws-sign2": "0.7.0",
|
||||
"aws4": "1.8.0",
|
||||
"caseless": "0.12.0",
|
||||
"combined-stream": "1.0.8",
|
||||
"extend": "3.0.2",
|
||||
"forever-agent": "0.6.1",
|
||||
"form-data": "2.3.3",
|
||||
"har-validator": "5.1.3",
|
||||
"http-signature": "1.2.0",
|
||||
"is-typedarray": "1.0.0",
|
||||
"isstream": "0.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"mime-types": "2.1.24",
|
||||
"oauth-sign": "0.9.0",
|
||||
"performance-now": "2.1.0",
|
||||
"qs": "6.5.2",
|
||||
"safe-buffer": "5.1.2",
|
||||
"tough-cookie": "2.4.3",
|
||||
"tunnel-agent": "0.6.0",
|
||||
"uuid": "3.3.2"
|
||||
}
|
||||
},
|
||||
"retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sandwich-stream": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
|
||||
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
|
||||
"requires": {
|
||||
"is-arrayish": "0.3.2"
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "0.2.4",
|
||||
"assert-plus": "1.0.0",
|
||||
"bcrypt-pbkdf": "1.0.2",
|
||||
"dashdash": "1.14.1",
|
||||
"ecc-jsbn": "0.1.2",
|
||||
"getpass": "0.1.7",
|
||||
"jsbn": "0.1.1",
|
||||
"safer-buffer": "2.1.2",
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
|
||||
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"superagent": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-5.1.0.tgz",
|
||||
"integrity": "sha512-7V6JVx5N+eTL1MMqRBX0v0bG04UjrjAvvZJTF/VDH/SH2GjSLqlrcYepFlpTrXpm37aSY6h3GGVWGxXl/98TKA==",
|
||||
"requires": {
|
||||
"component-emitter": "1.3.0",
|
||||
"cookiejar": "2.1.2",
|
||||
"debug": "4.1.1",
|
||||
"fast-safe-stringify": "2.0.6",
|
||||
"form-data": "2.3.3",
|
||||
"formidable": "1.2.1",
|
||||
"methods": "1.1.2",
|
||||
"mime": "2.4.4",
|
||||
"qs": "6.7.0",
|
||||
"readable-stream": "3.4.0",
|
||||
"semver": "6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"telegraf": {
|
||||
"version": "3.32.0",
|
||||
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.32.0.tgz",
|
||||
@@ -703,132 +93,6 @@
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/telegram-typings/-/telegram-typings-3.6.1.tgz",
|
||||
"integrity": "sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw=="
|
||||
},
|
||||
"text-hex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"requires": {
|
||||
"psl": "1.2.0",
|
||||
"punycode": "1.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
|
||||
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "2.1.1"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "1.3.0"
|
||||
}
|
||||
},
|
||||
"winston": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz",
|
||||
"integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==",
|
||||
"requires": {
|
||||
"async": "2.6.2",
|
||||
"diagnostics": "1.1.1",
|
||||
"is-stream": "1.1.0",
|
||||
"logform": "2.1.2",
|
||||
"one-time": "0.0.4",
|
||||
"readable-stream": "3.4.0",
|
||||
"stack-trace": "0.0.10",
|
||||
"triple-beam": "1.3.0",
|
||||
"winston-transport": "4.3.0"
|
||||
}
|
||||
},
|
||||
"winston-transport": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz",
|
||||
"integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==",
|
||||
"requires": {
|
||||
"readable-stream": "2.3.6",
|
||||
"triple-beam": "1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "2.0.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-10
@@ -1,25 +1,21 @@
|
||||
{
|
||||
"name": "@superalgos/clone-executor",
|
||||
"version": "1.0.51",
|
||||
"description": "Module responsible for executing the bots on the cloud.",
|
||||
"author": "Superalgos, ltd.",
|
||||
"name": "@superalgos/taskserver",
|
||||
"version": "2.0.0",
|
||||
"description": "Executes Tasks.",
|
||||
"author": "Superalgos.org",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Superalgos/CloneExecutor.git"
|
||||
"url": "https://github.com/Superalgos/TaskServer.git"
|
||||
},
|
||||
"main": "Run.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@superalgos/exchange-gateway": "0.0.10",
|
||||
"@superalgos/mqservice": "^0.0.17",
|
||||
"axios": "^0.19.0",
|
||||
"ccxt": "^1.21.82",
|
||||
"dotenv": "^8.0.0",
|
||||
"node-ipc": "^9.1.1",
|
||||
"telegraf": "^3.32.0",
|
||||
"winston": "^3.2.1"
|
||||
"telegraf": "^3.32.0"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user