Adding baseline with emails and confirmation checking.

This commit is contained in:
Matias Benitez committed 2018-07-21 11:47:45 -03:00
1 parent d501d4aeef
commit b4907f14ea
2 files changed
+335 -124

No files matched your search

+303 -115
View File
@@ -44,6 +44,13 @@
let stopLossEnabled = true;
let stopLossPorcentage = 0.02;
let lastBuyRate = assistant.remindMeOf(LAST_BUY_RATE_KEY);
if (lastBuyRate === undefined) {
let currentRate = assistant.getMarketRate();
lastBuyRate = currentRate;
assistant.rememberThis(LAST_BUY_RATE_KEY, lastBuyRate);
}
/*
This trading bot will use an strategy based on the interpretation of the Linear Regression Curve Channel.
*/
@@ -63,7 +70,7 @@
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.
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;
@@ -77,29 +84,56 @@
function businessLogic(callBack) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> Entering function."); }
let firstChannelTilt = 0;
getChannelTilt(botDecision);
getChannelTilt(firstTiltCheck);
function botDecision(err, channelTilt) {
function firstTiltCheck(err, channelTilt) {
try {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> botDecision -> Entering Function."); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> firstTiltCheck -> Entering Function."); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> botDecision -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> firstTiltCheck -> err = " + err.message);
callBack(global.DEFAULT_FAIL_RESPONSE);
} else {
if (channelTilt == 1) {
createBuyPosition(callBack);
firstChannelTilt = 1;
getSecondChannelTilt(secondTiltCheck);
} else if (channelTilt == -1) {
createSellPosition(callBack);
firstChannelTilt = -1;
getSecondChannelTilt(secondTiltCheck);
} else {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> botDecision -> Nothing to do, there isn't a sell or buy oportunity."); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> firstTiltCheck -> Nothing to do, there isn't a buy or sell oportunity."); }
callBack(global.DEFAULT_OK_RESPONSE);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> botDecision -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> firstTiltCheck -> err = " + err.message);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function secondTiltCheck(err, secondChannelTilt) {
try {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> secondTiltCheck -> Entering Function."); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> secondTiltCheck -> err = " + err.message);
callBack(global.DEFAULT_FAIL_RESPONSE);
} else {
if (firstChannelTilt == 1 && secondChannelTilt == 1) {
createBuyPosition(callBack);
}else if (firstChannelTilt == -1 && secondChannelTilt == -1) {
createSellPosition(callBack);
} else {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> secondTiltCheck -> Nothing to do, there isn't a buy or sell oportunity."); }
callBack(global.DEFAULT_OK_RESPONSE);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> secondTiltCheck -> err = " + err.message);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
@@ -154,7 +188,7 @@
}
}
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getChannelTilt -> onLRCPointsFileReceived. The expected LRC Point was not found.");
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getChannelTilt -> onLRCPointsFileReceived. The expected LRC Point was not found: "+bot.processDatetime.valueOf());
callBack(global.DEFAULT_FAIL_RESPONSE);
} else {
// Running live we will process last available LRCPoint only if it's delayed 25 minutes top
@@ -231,114 +265,54 @@
if (lrcPoint.max < lrcPoint.mid && lrcPoint.min > lrcPoint.mid && lrcPoint.mid < lrcPoint.min) {
if (lrcPoint.min > previousLRCPoint.min && lrcPoint.mid > previousLRCPoint.mid && lrcPoint.max > previousLRCPoint.max) {
channelTilt = CHANNEL_UP; // The channel points UP
// The channel points UP
channelTilt = CHANNEL_UP;
ruleApplied += "Rule_1.";
}
}
if (lrcPoint.min < lrcPoint.mid && lrcPoint.max > lrcPoint.mid && lrcPoint.mid < lrcPoint.max) {
if (lrcPoint.min < previousLRCPoint.min && lrcPoint.mid < previousLRCPoint.mid && lrcPoint.max < previousLRCPoint.max) {
channelTilt = CHANNEL_DOWN; // The channel points DOWN
// The channel points DOWN
channelTilt = CHANNEL_DOWN;
ruleApplied += "Rule_2.";
}
}
if (lrcPoint.min < previousLRCPoint.min && lrcPoint.mid <= previousLRCPoint.mid) {
// 15 AND 30 changed direction from up to down
if (checkToSellWithStopLoss()) {
channelTilt = CHANNEL_DOWN;
ruleApplied += "Rule_3a.";
}
if(checkToSellWithStopLoss()) {
channelTilt = CHANNEL_DOWN;
ruleApplied += "Rule_3a.";
}
}
if (lrcPoint.min > previousLRCPoint.min && lrcPoint.mid >= previousLRCPoint.mid) {
// 15 AND 30 changed direction from down to up
getLastCandleFromOlivia(onLastCandleFromOliviaReceived);
function onLastCandleFromOliviaReceived(candle) {
if (candle !== undefined && candle.close >= candle.open) {
//We will only fast buy if the current candle close, is greater than the open
channelTilt = CHANNEL_UP;
ruleApplied += "Rule_3b.";
}
let logMessage = bot.processDatetime.toISOString() + ". Rule: " + ruleApplied + "Tilt: " + channelTilt + " (" + Number(lrcPoint.min).toLocaleString() + "|" + Number(lrcPoint.mid).toLocaleString() + "|" + Number(lrcPoint.max).toLocaleString() + ")";
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> Results: " + logMessage); }
callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
}
} else {
let logMessage = bot.processDatetime.toISOString() + ". Rule: " + ruleApplied + "Tilt: " + channelTilt + " (" + Number(lrcPoint.min).toLocaleString() + "|" + Number(lrcPoint.mid).toLocaleString() + "|" + Number(lrcPoint.max).toLocaleString() + ")";
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> Results: " + logMessage); }
callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
channelTilt = CHANNEL_UP;
ruleApplied += "Rule_3b.";
}
let logMessage = bot.processDatetime.toISOString() + ". First Rule: " + ruleApplied + ". Tilt: " + channelTilt + " (" + Number(lrcPoint.min).toLocaleString() + "|" + Number(lrcPoint.mid).toLocaleString() + "|" + Number(lrcPoint.max).toLocaleString() + ")";
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> Results: " + logMessage); }
callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
}
function getLastCandleFromOlivia(callback) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> getLastCandleFromOlivia -> Entering Function."); }
let key = "AAMasters-AAOlivia-Candles-Multi-Period-Daily-dataSet.V1";
let oliviaStorage = assistant.dataDependencies.dataSets.get(key);
let dateTime = new Date(lrcPoint.begin);
let datePath = dateTime.getUTCFullYear() + "/" + pad(dateTime.getUTCMonth() + 1, 2) + "/" + pad(dateTime.getUTCDate(), 2);
let filePath = "Candles/Multi-Period-Daily/" + periodName + "/" + datePath;
let fileName = market.assetA + '_' + market.assetB + ".json"
oliviaStorage.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
try {
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] getLastCandleFromOlivia -> onFileReceived-> Entering Function."); }
let candleFile = JSON.parse(text);
let lastCandleOlivia;
for (let i = 0; i < candleFile.length; i++) {
if (candleFile[i][4] == lrcPoint.begin) {
lastCandleOlivia = {
open: candleFile[i][2],
close: candleFile[i][3],
min: candleFile[i][0],
max: candleFile[i][1],
begin: candleFile[i][4],
end: candleFile[i][5]
};
break;
}
}
callback(lastCandleOlivia);
} else {
logger.write(MODULE_NAME, "[WARN] getLastCandleFromOlivia -> onFileReceived -> Failed to get the file.");
callback(undefined);
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] getLastCandleFromOlivia -> onFileReceived -> err = " + err.message);
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
}
}
}
function checkToSellWithStopLoss() {
function checkToSellWithStopLoss() {
let allowSell = true;
let assetBBalance = assistant.getAvailableBalance().assetB;
let currentRate = assistant.getMarketRate();
let amountB = assistant.getAvailableBalance().assetB;
let amountA = amountB * currentRate;
let lastBuyRate = assistant.remindMeOf(LAST_BUY_RATE_KEY);
if (stopLossEnabled && assetBBalance > 0) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop Loss Enabled, checking to sell."); }
if (stopLossEnabled) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop Loss Enabled, checking to sell."); }
// Get the current investment value
let investment = 0;
if (assistant.getAvailableBalance() !== undefined) {
//Get our last buy, if any
if (lastBuyRate === undefined)
lastBuyRate = currentRate; // We assume we just bought
investment = assistant.getAvailableBalance().assetB * lastBuyRate;
}
@@ -346,11 +320,12 @@
let currentLoss = amountA - investment;
let stopLossValue = investment * stopLossPorcentage;
if (currentLoss >= 0) {
return true; // If we are winning sell.
} else if (currentLoss < 0) {
if (currentLoss > 0) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> No loss, we can sell."); }
} else if (assetBBalance > 0) {
if (Math.abs(currentLoss) > stopLossValue) {
let message = "Selling to avoid loss more than " + Number(stopLossPorcentage * 100).toLocaleString() + "% of our initial investment. ";
let message = "Sell to avoid loss more than " + Number(stopLossPorcentage * 100).toLocaleString() + "% of our initial investment. ";
message += "Combined ROI on current execution: ";
if (assistant.getCombinedProfits().assetA > 0) {
@@ -359,28 +334,184 @@
message += Number(assistant.getCombinedProfits().assetB).toLocaleString() + "%. ";
}
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop loss: " + message); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop loss, sell: " + message); }
assistant.sendMessage(3, "Stop Loss", message);
return true;
} else {
let currentRisk = currentLoss / investment;
let message = "Not selling now. Risking " + Number(currentRisk * 100).toLocaleString() + "% of our initial investment";
let message = "Not sell now. Risking " + Number(currentRisk * 100).toLocaleString() + "% of our initial investment";
message += ". Last Buy: $" + Number(lastBuyRate).toLocaleString();
message += ". Not selling at: $" + Number(currentRate).toLocaleString();
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop loss: " + message); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getChannelTilt -> applyBotRules -> manageStopLossConfiguration -> Stop loss, not sell: " + message); }
assistant.sendMessage(3, "Stop Loss", message);
return false;
allowSell = false;
}
}
} else {
return true;
}
return allowSell;
}
}
function getSecondChannelTilt(callBack) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getSecondChannelTilt -> Entering function."); }
const CHANNEL_DOWN = -1;
const CHANNEL_UP = 1;
const NO_CHANNEL = 0;
let lrcPoint, previousLRCPoint;
getLRCPointsMarketFile(onLRCPointsFileReceived);
function onLRCPointsFileReceived(err, lrcPointsFile) {
try {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getSecondChannelTilt -> onLRCPointsFileReceived."); }
let lastIndexLrcPointsFile = lrcPointsFile.length - 1;
let lastAvailableDateTime = lrcPointsFile[lastIndexLrcPointsFile][0];
if (bot.processDatetime.valueOf() <= lastAvailableDateTime || !isExecutionToday()) {
for (let i = lrcPointsFile.length-1; i >= 0; i--) {
if (bot.processDatetime.valueOf() >= lrcPointsFile[i][0] && bot.processDatetime.valueOf() < lrcPointsFile[i][1]) {
lrcPoint = {
begin: lrcPointsFile[i][0],
end: lrcPointsFile[i][1],
min: lrcPointsFile[i][2],
mid: lrcPointsFile[i][3],
max: lrcPointsFile[i][4]
};
if (i >= 1) {
let previous = i - 1;
previousLRCPoint = {
begin: lrcPointsFile[previous][0],
end: lrcPointsFile[previous][1],
min: lrcPointsFile[previous][2],
mid: lrcPointsFile[previous][3],
max: lrcPointsFile[previous][4]
};
applyBotRules();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getSecondChannelTilt -> onLRCPointsFileReceived. The expected previous LRC Point was not found.");
}
return;
}
}
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getSecondChannelTilt -> onLRCPointsFileReceived. The expected LRC Point was not found." + bot.processDatetime.valueOf() +". "+JSON.stringify(lrcPointsFile));
callBack(global.DEFAULT_FAIL_RESPONSE);
} else {
// Running live we will process last available LRCPoint only if it's delayed 25 minutes top
let maxTolerance = 25 * 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]
};
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]
};
applyBotRules();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> businessLogic -> getSecondChannelTilt -> onLRCPointsFileReceived. The expected previous LRC Point was not found.");
}
} else {
if (LOG_INFO === true) logger.write(MODULE_NAME, "[WARN] start -> getSecondChannelTilt -> onLRCPointsFileReceived. Available candle older than 5 minutes. Skeeping execution.");
callBack(global.DEFAULT_OK_RESPONSE, NO_CHANNEL); // TODO CUSTOM_OK_RESPONSE
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> getSecondChannelTilt -> onLRCPointsFileReceived -> err = " + err.message);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
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());
}
function onPreviousLRCPointsFileReceived(err, lrcPointsFile) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getSecondChannelTilt -> 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 -> getSecondChannelTilt -> applyBotRules -> LRC Point Found."); }
let channelTilt = NO_CHANNEL;
let ruleApplied = "";
if (lrcPoint.max < lrcPoint.mid && lrcPoint.min > lrcPoint.mid && lrcPoint.mid < lrcPoint.min) {
if (lrcPoint.min > previousLRCPoint.min && lrcPoint.mid > previousLRCPoint.mid && lrcPoint.max > previousLRCPoint.max) {
// The channel points UP
channelTilt = CHANNEL_UP;
ruleApplied += "Rule_1.";
}
}
if (lrcPoint.min < lrcPoint.mid && lrcPoint.max > lrcPoint.mid && lrcPoint.mid < lrcPoint.max) {
if (lrcPoint.min < previousLRCPoint.min && lrcPoint.mid < previousLRCPoint.mid && lrcPoint.max < previousLRCPoint.max) {
// The channel points DOWN
channelTilt = CHANNEL_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() + ". Second Rule: " + ruleApplied + ". Tilt: " + channelTilt + " (" + Number(lrcPoint.min).toLocaleString() + "|" + Number(lrcPoint.mid).toLocaleString() + "|" + Number(lrcPoint.max).toLocaleString() + ")";
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> getSecondChannelTilt -> applyBotRules -> Results: " + logMessage); }
callBack(global.DEFAULT_OK_RESPONSE, channelTilt);
}
}
@@ -391,14 +522,22 @@
let filePath = "LRC-Points/Multi-Period-Daily/" + periodName + "/" + datePath;
let fileName = market.assetA + '_' + market.assetB + ".json"
gaussStorage.getTextFile(filePath, fileName, onFileReceived);
if (bot.startMode === "Backtest" && bot.botCache.has(filePath)) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> getLRCPointsFile -> Getting the file from local cache."); }
cleanUpCache(bot.botCache, "LRC-Points/Multi-Period-Daily/" + periodName , dateTime);
callback(global.DEFAULT_OK_RESPONSE, bot.botCache.get(filePath));
} else {
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);
bot.botCache.set(filePath, lrcPointsFile);
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.");
@@ -406,6 +545,50 @@
return;
}
}
function cleanUpCache(fileCache, path, dateTimeCacheFile) {
let date = new Date(dateTimeCacheFile);
date.setDate(date.getDate() - 2);
let datePath = date.getUTCFullYear() + "/" + pad(date.getUTCMonth() + 1, 2) + "/" + pad(date.getUTCDate(), 2);
let cachePosition = path + '/' + datePath;
// Remove and go back one day
if (fileCache.has(cachePosition)) {
fileCache.delete(cachePosition);
date.setDate(date.getDate() - 1);
cleanUpCache(fileCache, date);
}
}
}
function getLRCPointsMarketFile(callback) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] getLRCPointsMarketFile -> Entering function."); }
let filePath = "LRC-Points/Multi-Period-Market/01-hs";
let fileName = market.assetA + '_' + market.assetB + ".json"
if (bot.startMode === "Backtest" && bot.botCache.has(filePath)) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] getLRCPointsMarketFile -> Getting the file from local cache."); }
callback(global.DEFAULT_OK_RESPONSE, bot.botCache.get(filePath));
} else {
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] getLRCPointsMarketFile -> onFileReceived > Entering Function."); }
let lrcPointsFile = JSON.parse(text);
bot.botCache.set(filePath, lrcPointsFile);
callback(global.DEFAULT_OK_RESPONSE, lrcPointsFile);
} else {
logger.write(MODULE_NAME, "[ERROR]getLRCPointsMarketFile -> onFileReceived -> Failed to get the file. Will abort the process and request a retry.");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return;
}
}
}
function createBuyPosition(callBack) {
@@ -415,23 +598,24 @@
let assetABalance = assistant.getAvailableBalance().assetA;
let currentRate = assistant.getMarketRate();
let amountA = assistant.getAvailableBalance().assetA;
let amountB = amountA / currentRate;
let amountB = Number((amountA / currentRate).toFixed(8));
if (positions.length > 0 && positions[0].type === "buy" && positions[0].status !== "executed" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 15)) {
if (positions.length > 0 && positions[0].type === "buy" && positions[0].status !== "executed" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 10)) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Moving an existing position to a new price: $" + Number(currentRate).toLocaleString()); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Moving an existing BUY position to a new price: $" + Number(currentRate).toLocaleString()); }
let message = "Moving an existing buy position to a new price: $" + Number(currentRate).toLocaleString();
assistant.sendMessage(6, "Moving Position", message);
message = bot.processDatetime.toISOString() + " - " + message;
assistant.sendEmail("Alerts", message, bot.emailSubscriptions);
assistant.rememberThis(LAST_BUY_RATE_KEY, currentRate);
assistant.movePosition(positions[0], currentRate, callBack);
} else if (assetABalance > 0) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> Artuditu put a new BUY position at price: $" + Number(currentRate).toLocaleString()); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Artuditu put a new BUY position at price: $" + Number(currentRate).toLocaleString()); }
let message = "Creating a new buy position. Price: $" + Number(currentRate).toLocaleString();
if (assistant.getCombinedProfits() !== undefined) {
@@ -444,12 +628,13 @@
}
assistant.sendMessage(7, "Buying", message);
message = bot.processDatetime.toISOString() + " - " + message;
assistant.sendEmail("Alerts", message, bot.emailSubscriptions);
assistant.rememberThis(LAST_BUY_RATE_KEY, currentRate);
assistant.putPosition("buy", currentRate, amountA, amountB, callBack);
} else {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Not enough available balance to buy."); }
@@ -466,17 +651,18 @@
let amountB = assistant.getAvailableBalance().assetB;
let amountA = amountB * currentRate;
if (positions.length > 0 && positions[0].type === "sell" && positions[0].status !== "executed" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 15)) {
if (positions.length > 0 && positions[0].type === "sell" && positions[0].status !== "executed" && (bot.processDatetime.valueOf() - positions[0].date) > (60000 * 10)) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> Artuditu is moving an existing position to a new rate: " + Number(currentRate).toLocaleString()); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> Artuditu is moving an existing SELL position to a new price: $" + Number(currentRate).toLocaleString()); }
let message = "Moving an existing sell position to a new price: $" + Number(currentRate).toLocaleString();
assistant.sendMessage(6, "Moving Position", message);
message = bot.processDatetime.toISOString() + " - " + message;
assistant.sendEmail("Alerts", message, bot.emailSubscriptions);
assistant.movePosition(positions[0], currentRate, callBack);
} else if (assetBBalance > 0) {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> Artuditu put a new SELL position at price: $" + Number(currentRate).toLocaleString()); }
let message = "Creating a new sell position. Price: $" + Number(currentRate).toLocaleString();
@@ -489,11 +675,13 @@
}
}
assistant.sendMessage(7, "Selling", message);
message = bot.processDatetime.toISOString() + " - " + message;
assistant.sendEmail("Alerts", message, bot.emailSubscriptions);
assistant.putPosition("sell", currentRate, amountA, amountB, callBack);
} else {
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createBuyPosition -> There is not enough available balance to sell. Available balance: " + assetBBalance); }
if (LOG_INFO === true) { logger.write(MODULE_NAME, "[INFO] start -> businessLogic -> createSellPosition -> There is not enough available balance to sell."); }
callBack(global.DEFAULT_OK_RESPONSE);
}
+32 -9
View File
@@ -16,26 +16,27 @@
"description": "Simple trading strategy to be used as a template.",
"startMode": {
"live": {
"run": "true",
"run": "false",
"resumeExecution": "false"
},
"backtest": {
"run": "false",
"beginDatetime": "2018-06-24T18:00:00.000Z",
"endDatetime": "2018-06-28T11:00:00.000Z",
"waitTime": 500
"run": "true",
"beginDatetime": "2018-04-11T00:00:00.000Z",
"endDatetime": "2018-06-17T23:59:59.000Z",
"waitTime": 1
},
"competition": {
"run": "false",
"beginDatetime": "2018-06-30T00:00:00.000Z",
"endDatetime": "2018-07-01T23:59:59.000Z",
"resumeExecution": "false"
"beginDatetime": "2018-07-04T00:00:00.000Z",
"endDatetime": "2018-07-06T23:59:59.000Z",
"resumeExecution": "true"
}
},
"normalWaitTime": 60000,
"retryWaitTime": 10000,
"sleepWaitTime": 3600000,
"comaWaitTime": 86400000,
"timePeriod": 1800000,
"statusDependencies": [
{
"devTeam": "AAVikings",
@@ -47,6 +48,16 @@
"process": "Multi-Period-Daily",
"dataSetVersion": "dataSet.V1"
},
{
"devTeam": "AAVikings",
"bot": "AAGauss",
"botVersion": {
"major": 1,
"minor": 0
},
"process": "Multi-Period-Market",
"dataSetVersion": "dataSet.V1"
},
{
"devTeam": "AAVikings",
"bot": "AAArtudito",
@@ -70,6 +81,17 @@
"dataSetVersion": "dataSet.V1",
"dataSet": "Multi-Period-Daily"
},
{
"devTeam": "AAVikings",
"bot": "AAGauss",
"botVersion": {
"major": 1,
"minor": 0
},
"product": "LRC-Points",
"dataSetVersion": "dataSet.V1",
"dataSet": "Multi-Period-Market"
},
{
"devTeam": "AAMasters",
"bot": "AABruce",
@@ -174,5 +196,6 @@
"moduleName": "History"
}
}
]
],
"emailSubscriptions": "mati108@gmail.com"
}