diff --git a/Project.njsproj b/Project.njsproj
index c3fab12e5..319a734ad 100644
--- a/Project.njsproj
+++ b/Project.njsproj
@@ -14,6 +14,7 @@
14.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
Project
+ Debug|Any CPU
diff --git a/Trading-Process/User.Bot.js b/Trading-Process/User.Bot.js
index 60ee46e43..281b70369 100644
--- a/Trading-Process/User.Bot.js
+++ b/Trading-Process/User.Bot.js
@@ -1,12 +1,8 @@
-exports.newUserBot = function newUserBot(BOT, DEBUG_MODULE, COMMONS_MODULE) {
- let bot = BOT;
+exports.newUserBot = function newUserBot(bot, logger) {
- const FULL_LOG = true;
const MODULE_NAME = "User Bot";
+ const FULL_LOG = true;
const LOG_INFO = true;
- const logger = DEBUG_MODULE.newDebugLog();
- logger.fileName = MODULE_NAME;
- logger.bot = bot;
let thisObject = {
initialize: initialize,
@@ -20,7 +16,7 @@
function initialize(pAssistant, callBackFunction) {
try {
- if (LOG_INFO === true) { logger.write("[INFO] initialize -> Entering function."); }
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
logger.fileName = MODULE_NAME;
@@ -32,159 +28,92 @@
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
- logger.write("[ERROR] initialize -> onDone -> err = " + err.message);
+ logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = " + err.message);
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
}
}
function start(callBackFunction) {
- try {
- if (LOG_INFO === true) { logger.write("[INFO] start -> Entering function."); }
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
- let market = global.MARKET;
- /*
+ let market = global.MARKET;
- This trading bot will use an strategy based on the interpretation of the Linear Regression Curve Channel.
+ /*
+ This trading bot will use an strategy based on the interpretation of the Linear Regression Curve Channel.
+ */
- */
+ businessLogic(onDone);
- businessLogic(onDone);
-
- function onDone(err) {
- try {
- switch (err.result) {
- case global.DEFAULT_OK_RESPONSE.result: {
- logger.write("[INFO] start -> onDone -> Execution finished well. :-)");
- callBackFunction(global.DEFAULT_OK_RESPONSE);
- 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("[ERROR] start -> onDone -> Retry Later. Requesting Execution Retry.");
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
- case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
- logger.write("[ERROR] start -> onDone -> Operation Failed. Aborting the process. err = " + err.message);
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
+ function onDone(err) {
+ try {
+ switch (err.result) {
+ case global.DEFAULT_OK_RESPONSE.result: {
+ logger.write(MODULE_NAME, "[INFO] start -> onDone -> Execution finished well. :-)");
+ callBackFunction(global.DEFAULT_OK_RESPONSE);
+ 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] start -> onDone -> Retry Later. Requesting Execution Retry.");
+ callBackFunction(global.DEFAULT_RETRY_RESPONSE);
+ return;
+ }
+ case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
+ logger.write(MODULE_NAME, "[ERROR] start -> onDone -> Operation Failed. Aborting the process. err = " + err.message);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
}
- } catch (err) {
- logger.write("[ERROR] start -> onDone -> err = " + err.message);
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
}
+ } catch (err) {
+ logger.write(MODULE_NAME, "[ERROR] start -> onDone -> err = " + err.message);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
+ }
- function businessLogic(callBack) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> businessLogic -> Entering function."); }
+ function businessLogic(callBack) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> Entering function."); }
- getChannelTilt(botDecision);
+ getChannelTilt(botDecision);
- function botDecision(err, channelTilt) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> businessLogic -> botDecision -> LRC Channel Tilt:" + channelTilt); }
+ function botDecision(err, channelTilt) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> botDecision -> LRC Channel Tilt:" + channelTilt); }
- if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
- logger.write("[ERROR] start -> businessLogic -> err = " + err.message);
- callBack(global.DEFAULT_RETRY_RESPONSE);
+ if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
+ logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> botDecision -> err = " + err.message);
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ } else {
+ if (channelTilt == 1) {
+ createBuyPosition(callBack);
+ } else if (channelTilt == -1) {
+ createSellPosition(callBack);
} else {
- if (channelTilt == 1) {
- createBuyPosition(callBack);
- } else if (channelTilt == -1) {
- createSellPosition(callBack);
- } else {
- if (LOG_INFO === true) { logger.write("[INFO] start -> processBotDecision -> Nothing to do, there isn't a sell or buy oportunity."); }
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> botDecision -> Nothing to do, there isn't a sell or buy oportunity."); }
- callBack(global.DEFAULT_OK_RESPONSE);
- }
+ callBack(global.DEFAULT_OK_RESPONSE);
}
}
- }
+ }
+ }
- function createBuyPosition(callBack) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> createBuyPosition -> Entering function."); }
-
- let positions = assistant.getPositions();
- let assetABalance = assistant.getAvailableBalance().assetA;
- let currentRate = assistant.getMarketRate();
- let amountA = assistant.getAvailableBalance().assetA;
- let amountB = amountA / currentRate;
-
- if(positions.length > 0 && positions[0].type === "buy" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 5)){
-
- assistant.movePosition(positions[0], currentRate, callBack);
-
- if (LOG_INFO === true) { logger.write("[INFO] start -> createBuyPosition -> Artuditu is moving an existing position to a new rate: " + currentRate.toFixed(8) + ". Position: " + JSON.stringify(positions[0])); }
-
- let message = "I'm moving an existing buy position to a new rate: " + currentRate.toFixed(8);
- assistant.sendMessage(1, "Moving Position", message);
+ function getChannelTilt(callBack) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getChannelTilt -> Entering function."); }
-
- } else if(assetABalance > 0){
-
- assistant.putPosition("buy", currentRate, amountA, amountB, callBack);
-
- let message = "I'm creating a new buy position at rate: " + currentRate.toFixed(8) + ". " + MARKET.assetA +" amount: " + amountA.toFixed(8) + ". " + MARKET.assetB + " amount: " + amountB.toFixed(8);
- assistant.sendMessage(1, "Buying", message);
-
- } else {
- if (LOG_INFO === true) { logger.write("[INFO] start -> createBuyPosition -> There is not enough available balance to buy. Available balance: " + assetABalance ); }
-
- callBack(global.DEFAULT_OK_RESPONSE);
- }
- }
-
- function createSellPosition(callBack) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> createSellPosition -> Entering function."); }
-
- let positions = assistant.getPositions();
- let assetBBalance = assistant.getAvailableBalance().assetB;
- let currentRate = assistant.getMarketRate();
- let amountB = assistant.getAvailableBalance().assetB;
- let amountA = amountB * currentRate;
+ const CHANNEL_DOWN = -1;
+ const CHANNEL_UP = 1;
+ const NO_CHANNEL = 0;
+ let lrcPoint, previousLRCPoint;
- if(positions.length > 0 && positions[0].type === "sell" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 5)){
-
- assistant.movePosition(positions[0], currentRate, callBack);
-
- if (LOG_INFO === true) { logger.write("[INFO] start -> createBuyPosition -> Artuditu is moving an existing position to a new rate: " + currentRate.toFixed(8) + ". Position: " + JSON.stringify(positions[0])); }
-
- let message = "I'm moving an existing sell position to a new rate: " + currentRate.toFixed(8);
- assistant.sendMessage(1, "Moving Position", message);
+ let queryDate = new Date(bot.processDatetime);
+ getLRCPointsFile(queryDate, onLRCPointsFileReceived);
- }else if(assetBBalance > 0){
-
- assistant.putPosition("sell", currentRate, amountA, amountB, callBack);
-
- if (LOG_INFO === true) { logger.write("[INFO] start -> createSellPosition -> Artuditu put a new SELL Position at rate: " + currentRate + ". Amount traded asset A: " + amountA + ". Amount traded asset B: " + amountB); }
-
- let message = "I'm creating a new sell position at rate: " + currentRate.toFixed(8) + ". " + MARKET.assetA +" amount: " + amountA.toFixed(8) + ". " + MARKET.assetB + " amount: " + amountB.toFixed(8);
- assistant.sendMessage(1, "Selling", message);
-
- } else {
- if (LOG_INFO === true) { logger.write("[INFO] start -> createBuyPosition -> There is not enough available balance to sell. Available balance: " + assetBBalance ); }
-
- callBack(global.DEFAULT_OK_RESPONSE);
- }
-
- }
+ function onLRCPointsFileReceived(err, lrcPointsFile) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getChannelTilt -> onLRCPointsFileReceived."); }
- function getChannelTilt(callBack) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> getChannelTilt -> Entering function."); }
-
- const CHANNEL_DOWN = -1;
- const CHANNEL_UP = 1;
- const NO_CHANNEL = 0;
- let lrcPoint, previousLRCPoint;
-
- let queryDate = new Date(bot.processDatetime);
- getLRCPointsFile(queryDate, onLRCPointsFileReceived);
-
- function onLRCPointsFileReceived(err, lrcPointsFile) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> getChannelTilt -> onLRCPointsFileReceived."); }
+ let lastIndexLrcPointsFile = lrcPointsFile.length - 1;
+ let lastAvailableDateTime = lrcPointsFile[lastIndexLrcPointsFile][0];
+ if (bot.processDatetime.valueOf() <= lastAvailableDateTime || !isExecutionToday()) {
for (let i = 0; i < lrcPointsFile.length; i++) {
-
- if (lrcPointsFile[i][0] === bot.processDatetime.valueOf()) {
+ if (bot.processDatetime.valueOf() >= lrcPointsFile[i][0] && bot.processDatetime.valueOf() < lrcPointsFile[i][1]) {
lrcPoint = {
begin: lrcPointsFile[i][0],
end: lrcPointsFile[i][1],
@@ -192,7 +121,6 @@
mid: lrcPointsFile[i][3],
max: lrcPointsFile[i][4]
};
-
if (i >= 1) {
let previous = i - 1;
previousLRCPoint = {
@@ -209,106 +137,215 @@
queryDate.setDate(queryDate.getDate() - 1);
getLRCPointsFile(queryDate, onPreviousLRCPointsFileReceived);
}
-
return;
}
}
- callBack(global.DEFAULT_OK_RESPONSE, NO_CHANNEL);
- }
+ logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getChannelTilt -> onLRCPointsFileReceived. The expected LRC Point was not found.");
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ } else {
+ // Running live we will process last available LRCPoint only if it's delayed 5 minutes top
+ let maxTolerance = 5 * 60 * 1000;
+ if (bot.processDatetime.valueOf() <= (lastAvailableDateTime + maxTolerance)) {
+ lrcPoint = {
+ begin: lrcPointsFile[lastIndexLrcPointsFile][0],
+ end: lrcPointsFile[lastIndexLrcPointsFile][1],
+ min: lrcPointsFile[lastIndexLrcPointsFile][2],
+ mid: lrcPointsFile[lastIndexLrcPointsFile][3],
+ max: lrcPointsFile[lastIndexLrcPointsFile][4]
+ };
- function onPreviousLRCPointsFileReceived(err, lrcPointsFile) {
- if (LOG_INFO === true) { logger.write("[INFO] start -> getChannelTilt -> onLRCPointsFileReceived."); }
+ if (lastIndexLrcPointsFile >= 1) {
+ let previous = lastIndexLrcPointsFile - 1;
+ previousLRCPoint = {
+ begin: lrcPointsFile[previous][0],
+ end: lrcPointsFile[previous][1],
+ min: lrcPointsFile[previous][2],
+ mid: lrcPointsFile[previous][3],
+ max: lrcPointsFile[previous][4]
+ };
- let previous = lrcPointsFile.length - 2;
- previousLRCPoint = {
- begin: lrcPointsFile[previous][0],
- end: lrcPointsFile[previous][1],
- min: lrcPointsFile[previous][2],
- mid: lrcPointsFile[previous][3],
- max: lrcPointsFile[previous][4]
- };
+ applyBotRules();
- applyBotRules();
- }
-
- function applyBotRules() {
- if (LOG_INFO === true) { logger.write("[INFO] start -> getChannelTilt -> applyBotRules -> LRC Point Found: " + JSON.stringify(lrcPoint)); }
-
- let channelTilt = NO_CHANNEL;
- let ruleApplied = "";
-
- if (lrcPoint.mid < lrcPoint.mid && lrcPoint.min > lrcPoint.mid && lrcPoint.mid < lrcPoint.min) {
- if (lrcPoint.min > previousLrc15 && lrcPoint.mid > previousLrc30 && lrcPoint.mid > previousLrc60) {
- channelTilt = CHANNEL_UP; // The channel points UP
- ruleApplied += "Rule_1.";
- }
- }
-
- if (lrcPoint.min < lrcPoint.mid && lrcPoint.mid > lrcPoint.mid && lrcPoint.mid < lrcPoint.mid) {
- if (lrcPoint.min < previousLrc15 && lrcPoint.mid < previousLrc30 && lrcPoint.mid < previousLrc60) {
- channelTilt = CHANNEL_DOWN; // The channel points DOWN
- ruleApplied += "Rule_2.";
- }
- }
-
- if (lrcPoint.min < previousLrc15 && lrcPoint.mid <= previousLrc30) {
- // 15 AND 30 changed direction from up to down
- channelTilt = CHANNEL_DOWN;
- ruleApplied += "Rule_3a.";
- }
-
- if (lrcPoint.min > previousLrc15 && lrcPoint.mid >= previousLrc30) {
- // 15 AND 30 changed direction from down to up
- channelTilt = CHANNEL_UP;
- ruleApplied += "Rule_3b.";
- }
-
- let logMessage = bot.processDatetime.toISOString() + "\t" + ruleApplied + "\t" + channelTilt + "\t" + lrcPoint.min + "\t" + lrcPoint.mid + "\t" + lrcPoint.mid;
- if (LOG_INFO === true) { logger.write("[INFO] start -> getChannelTilt -> applyBotRules -> Results: " + logMessage); }
-
- callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
-
- }
- }
-
- function getLRCPointsFile(dateTime, callback) {
- try {
- if (FULL_LOG === true) { logger.write("[INFO] start -> getChannelTilt -> getLRCPointsFile -> Entering function."); }
-
- let periodName = "30-min";
- let datePath = dateTime.getUTCFullYear() + "/" + pad(dateTime.getUTCMonth() + 1, 2) + "/" + pad(dateTime.getUTCDate(), 2);
- let filePath = "LRC-Points/Multi-Period-Daily/" + periodName + "/" + datePath;
- let fileName = market.assetA + '_' + market.assetB + ".json"
-
- gaussStorage.getTextFile(filePath, fileName, onFileReceived);
-
- function onFileReceived(err, text) {
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- if (FULL_LOG === true) { logger.write("[INFO] start -> getChannelTilt -> getLRCPointsFile -> onFileReceived > Entering Function."); }
-
- let lrcPointsFile = JSON.parse(text);
- callback(global.DEFAULT_OK_RESPONSE, lrcPointsFile);
} else {
- logger.write("[ERROR] start -> getChannelTilt -> getLRCPointsFile -> onFileReceived -> Failed to get the file. Will abort the process and request a retry.");
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
- return;
+ queryDate.setDate(queryDate.getDate() - 1);
+ getLRCPointsFile(queryDate, onPreviousLRCPointsFileReceived);
}
- }
- } catch (err) {
- logger.write("[ERROR] start -> getChannelTilt -> getLRCPointsFile -> err = " + err.message);
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
+ } else {
+ if (LOG_INFO === true) logger.write(MODULE_NAME, "[WARN] start -> getChannelTilt -> onLRCPointsFileReceived. Available candle older than 5 minutes. Skeeping execution.");
+
+ callBack(global.DEFAULT_OK_RESPONSE, NO_CHANNEL); // TODO CUSTOM_OK_RESPONSE
+ }
}
}
- function pad(str, max) {
- str = str.toString();
- return str.length < max ? pad("0" + str, max) : str;
+ function isExecutionToday() {
+ let localDate = new Date();
+ let today = new Date(Date.UTC(
+ localDate.getUTCFullYear(),
+ localDate.getUTCMonth(),
+ localDate.getUTCDate()));
+
+ return (today.getUTCFullYear() === bot.processDatetime.getUTCFullYear()
+ && today.getUTCMonth() === bot.processDatetime.getUTCMonth()
+ && today.getUTCDate() === bot.processDatetime.getUTCDate());
}
- } catch (err) {
- logger.write("[ERROR] start -> err = " + err.message);
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
+ function onPreviousLRCPointsFileReceived(err, lrcPointsFile) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> onLRCPointsFileReceived."); }
+
+ let previous = lrcPointsFile.length - 1;
+ previousLRCPoint = {
+ begin: lrcPointsFile[previous][0],
+ end: lrcPointsFile[previous][1],
+ min: lrcPointsFile[previous][2],
+ mid: lrcPointsFile[previous][3],
+ max: lrcPointsFile[previous][4]
+ };
+
+ applyBotRules();
+ }
+
+ function applyBotRules() {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> LRC Point Found: " + JSON.stringify(lrcPoint)); }
+
+ let channelTilt = NO_CHANNEL;
+ let ruleApplied = "";
+
+ if (lrcPoint.mid < lrcPoint.mid && lrcPoint.min > lrcPoint.mid && lrcPoint.mid < lrcPoint.min) {
+ if (lrcPoint.min > previousLRCPoint.min && lrcPoint.mid > previousLRCPoint.mid && lrcPoint.mid > previousLRCPoint.max) {
+ channelTilt = CHANNEL_UP; // The channel points UP
+ ruleApplied += "Rule_1.";
+ }
+ }
+
+ if (lrcPoint.min < lrcPoint.mid && lrcPoint.mid > lrcPoint.mid && lrcPoint.mid < lrcPoint.mid) {
+ if (lrcPoint.min < previousLRCPoint.min && lrcPoint.mid < previousLRCPoint.mid && lrcPoint.mid < previousLRCPoint.max) {
+ channelTilt = CHANNEL_DOWN; // The channel points DOWN
+ ruleApplied += "Rule_2.";
+ }
+ }
+
+ if (lrcPoint.min < previousLRCPoint.min && lrcPoint.mid <= previousLRCPoint.mid) {
+ // 15 AND 30 changed direction from up to down
+ channelTilt = CHANNEL_DOWN;
+ ruleApplied += "Rule_3a.";
+ }
+
+ if (lrcPoint.min > previousLRCPoint.min && lrcPoint.mid >= previousLRCPoint.mid) {
+ // 15 AND 30 changed direction from down to up
+ channelTilt = CHANNEL_UP;
+ ruleApplied += "Rule_3b.";
+ }
+
+ let logMessage = bot.processDatetime.toISOString() + "\t" + ruleApplied + "\t" + channelTilt + "\t" + lrcPoint.min + "\t" + lrcPoint.mid + "\t" + lrcPoint.mid;
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> Results: " + logMessage); }
+
+ callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
+ }
}
+
+ function getLRCPointsFile(dateTime, callback) {
+ try {
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getLRCPointsFile -> Entering function."); }
+
+ let periodName = "30-min";
+ let datePath = dateTime.getUTCFullYear() + "/" + pad(dateTime.getUTCMonth() + 1, 2) + "/" + pad(dateTime.getUTCDate(), 2);
+ let filePath = "LRC-Points/Multi-Period-Daily/" + periodName + "/" + datePath;
+ let fileName = market.assetA + '_' + market.assetB + ".json"
+
+ gaussStorage.getTextFile(filePath, fileName, onFileReceived);
+
+ function onFileReceived(err, text) {
+ if (err.result === global.DEFAULT_OK_RESPONSE.result) {
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> getLRCPointsFile -> onFileReceived > Entering Function."); }
+
+ let lrcPointsFile = JSON.parse(text);
+ callback(global.DEFAULT_OK_RESPONSE, lrcPointsFile);
+ } else {
+ logger.write(MODULE_NAME, "[ERROR] start -> getChannelTilt -> getLRCPointsFile -> onFileReceived -> Failed to get the file. Will abort the process and request a retry.");
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
+ }
+
+ } catch (err) {
+ logger.write(MODULE_NAME, "[ERROR] start -> getChannelTilt -> getLRCPointsFile -> err = " + err.message);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ }
+ }
+
+ function createBuyPosition(callBack) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Entering function."); }
+
+ let positions = assistant.getPositions();
+ let assetABalance = assistant.getAvailableBalance().assetA;
+ let currentRate = assistant.getMarketRate();
+ let amountA = assistant.getAvailableBalance().assetA;
+ let amountB = amountA / currentRate;
+
+ if(positions.length > 0 && positions[0].type === "buy" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 5)){
+
+ assistant.movePosition(positions[0], currentRate, callBack);
+
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Artuditu is moving an existing position to a new rate: " + currentRate.toFixed(8) + ". Position: " + JSON.stringify(positions[0])); }
+
+ let message = "I'm moving an existing buy position to a new rate: " + currentRate.toFixed(8);
+ assistant.sendMessage(1, "Moving Position", message);
+
+
+ } else if(assetABalance > 0){
+
+ assistant.putPosition("buy", currentRate, amountA, amountB, callBack);
+
+ let message = "I'm creating a new buy position at rate: " + currentRate.toFixed(8) + ". " + MARKET.assetA +" amount: " + amountA.toFixed(8) + ". " + MARKET.assetB + " amount: " + amountB.toFixed(8);
+ assistant.sendMessage(1, "Buying", message);
+
+ } else {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> There is not enough available balance to buy. Available balance: " + assetABalance ); }
+
+ callBack(global.DEFAULT_OK_RESPONSE);
+ }
+ }
+
+ function createSellPosition(callBack) {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> Entering function."); }
+
+ let positions = assistant.getPositions();
+ let assetBBalance = assistant.getAvailableBalance().assetB;
+ let currentRate = assistant.getMarketRate();
+ let amountB = assistant.getAvailableBalance().assetB;
+ let amountA = amountB * currentRate;
+
+ if(positions.length > 0 && positions[0].type === "sell" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 5)){
+
+ assistant.movePosition(positions[0], currentRate, callBack);
+
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Artuditu is moving an existing position to a new rate: " + currentRate.toFixed(8) + ". Position: " + JSON.stringify(positions[0])); }
+
+ let message = "I'm moving an existing sell position to a new rate: " + currentRate.toFixed(8);
+ assistant.sendMessage(1, "Moving Position", message);
+
+ }else if(assetBBalance > 0){
+
+ assistant.putPosition("sell", currentRate, amountA, amountB, callBack);
+
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> Artuditu put a new SELL Position at rate: " + currentRate + ". Amount traded asset A: " + amountA + ". Amount traded asset B: " + amountB); }
+
+ let message = "I'm creating a new sell position at rate: " + currentRate.toFixed(8) + ". " + MARKET.assetA +" amount: " + amountA.toFixed(8) + ". " + MARKET.assetB + " amount: " + amountB.toFixed(8);
+ assistant.sendMessage(1, "Selling", message);
+
+ } else {
+ if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> There is not enough available balance to sell. Available balance: " + assetBBalance ); }
+
+ callBack(global.DEFAULT_OK_RESPONSE);
+ }
+ }
+
+ function pad(str, max) {
+ str = str.toString();
+ return str.length < max ? pad("0" + str, max) : str;
+ }
+
}
};
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..4c1670f94
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,5 @@
+{
+ "name": "AAArtudito",
+ "version": "1.0.0",
+ "lockfileVersion": 1
+}
diff --git a/package.json b/package.json
index bf08fd3ef..a3a80b8a2 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,5 @@
},
"author": "Matias-Benitez",
"license": "ISC",
- "dependencies": {
- }
+ "dependencies": {}
}