Live Trading working tested at Binance

This commit is contained in:
Luis Fernando Molina committed 2020-02-07 16:50:11 +01:00
1 parent 1ba29a7bad
commit 15b8a9044d
63 files changed
+1675 -1970

No files matched your search

+69 -307
View File
@@ -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);
}
}
+1 -1
View File
@@ -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));
+160
View File
@@ -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)
}
};
+2 -2
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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)
+24 -260
View File
@@ -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
View File
@@ -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
+2 -738
View File
@@ -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
View File
@@ -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"
}
}