diff --git a/Session.js b/Session.js index 23613c37c..2db5d9190 100644 --- a/Session.js +++ b/Session.js @@ -8,14 +8,15 @@ initialize: initialize } + const SOCIAL_BOTS_MODULE = require('./SocialBots.js') + let socialBotsModule = SOCIAL_BOTS_MODULE.newSocialBots(bot, logger) + return thisObject; function initialize(pProcessConfig, callBackFunction) { try { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - let telegramAPI - /* Initialize this info so that everything is logged propeerly */ bot.SESSION = { @@ -59,34 +60,14 @@ bot.SESSION = JSON.parse(message.event.session) bot.DEPENDENCY_FILTER = JSON.parse(message.event.dependencyFilter) bot.RESUME = message.event.resume + bot.SESSION.stop = sessionStop // stop function - /* Setup the APP_SCHEMA_MAP based on the APP_SCHEMA_ARRAY */ - bot.APP_SCHEMA_MAP = new Map() - for (let i = 0; i < bot.APP_SCHEMA_ARRAY.length; i++) { - let nodeDefinition = bot.APP_SCHEMA_ARRAY[i] - let key = nodeDefinition.type - bot.APP_SCHEMA_MAP.set(key, nodeDefinition) - } - - /* Set the folderName for logging, reports, context and data output */ - let config - if (bot.SESSION.config !== undefined) { - config = bot.SESSION.config - if (config.folderName === undefined) { - bot.SESSION.folderName = bot.SESSION.id - } else { - bot.SESSION.folderName = config.folderName + "-" + bot.SESSION.id - } - } + setUpAppSchema() + setUpSessionFolderName() if (checkParemeters() === false) { return } - - /* Extract values from different sources and consolidate them under one structure that is going to be used later on. */ - setValuesToUse(message) - - /* Set up Social Bots */ - initializeSocialBots() + socialBotsModule.initialize() let allGood switch (bot.SESSION.type) { @@ -113,9 +94,44 @@ } else { bot.STOP_SESSION = true } + + socialBotsModule.sendMessage(bot.SESSION.type + " '" + bot.SESSION.name + "' was started.") } catch (err) { parentLogger.write(MODULE_NAME, "[ERROR] initialize -> runSession -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function stopSession(commandOrigin) { + try { + if (reason === undefined) { commandOrigin = ' from the User Interface.' } + socialBotsModule.sendMessage(bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped " + commandOrigin) + bot.STOP_SESSION = true + socialBotsModule.finalize() + } catch (err) { + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> stopSession -> err = " + err.stack); + } + } + + function setUpAppSchema() { + /* Setup the APP_SCHEMA_MAP based on the APP_SCHEMA_ARRAY */ + bot.APP_SCHEMA_MAP = new Map() + for (let i = 0; i < bot.APP_SCHEMA_ARRAY.length; i++) { + let nodeDefinition = bot.APP_SCHEMA_ARRAY[i] + let key = nodeDefinition.type + bot.APP_SCHEMA_MAP.set(key, nodeDefinition) + } + } + + function setUpSessionFolderName() { + /* Set the folderName for logging, reports, context and data output */ + let config + if (bot.SESSION.config !== undefined) { + config = bot.SESSION.config + if (config.folderName === undefined) { + bot.SESSION.folderName = bot.SESSION.id + } else { + bot.SESSION.folderName = config.folderName + "-" + bot.SESSION.id + } } } @@ -147,6 +163,30 @@ if (bot.SESSION.parameters.timeRange.config.finalDatetime === undefined) { // if the finalDatetime is missing we create a default one. bot.SESSION.parameters.timeRange.config.finalDatetime = (new Date()).valueOf() } + /* Session Type Forced Values */ + switch (bot.SESSION.type) { + case 'Live Trading Session': { + if (bot.SESSION.parameters.timeRange.config.finalDatetime.valueOf() > (new Date()).valueOf()) { + bot.SESSION.parameters.timeRange.config.finalDatetime = new Date() + } + break + } + case 'Live Trading Session': { + bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() + bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) + break + } + case 'Fordward Testing Session': { + bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() + bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) + break + } + case 'Paper Trading Session': { + bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() + bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) + break + } + } /* Time Frame */ if (bot.SESSION.parameters.timeFrame === undefined) { @@ -233,48 +273,20 @@ return true } - - function stopSession(message) { - try { - bot.STOP_SESSION = true - finalizeSocialBots() - } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> stopSession -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function checkDatetimes() { - if (bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf() < (new Date()).valueOf()) { - if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> checkDatetimes -> Overriding initialDatetime with present datetime because " + bot.SESSION.parameters.timeRange.config.initialDatetime + " is in the past."); } - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() - } - if (bot.SESSION.parameters.timeRange.config.finalDatetime.valueOf() < (new Date()).valueOf()) { - if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> checkDatetimes -> Overriding finalDatetime with present datetime plus one year because " + bot.SESSION.parameters.timeRange.config.finalDatetime + " is in the past."); } - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date() + ONE_YEAR_IN_MILISECONDS - } - } - function startBackTesting(message) { - bot.startMode = "Backtest" - if (bot.SESSION.parameters.timeRange.config.finalDatetime.valueOf() > (new Date()).valueOf()) { - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date() - } - bot.resumeExecution = false; - bot.hasTheBotJustStarted = true - bot.multiPeriodProcessDatetime = new Date(bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf()) + bot.resumeExecution = false; // TODO change this for the new way of handling resuming + bot.hasTheBotJustStarted = true // TODO see if this is necesary + bot.multiPeriodProcessDatetime = new Date(bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf()) // TODO see if this is necesary return true } function startLiveTrading(message) { - if (process.env.KEY === undefined || process.env.SECRET === undefined) { + if (process.env.KEY === undefined || process.env.SECRET === undefined) { // TODO Remove this from Process .env if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[ERROR] initialize -> startLiveTrading -> Key 'codeName' or 'secret' not provided. Plese check that and try again."); } - return + return false } - bot.startMode = "Live" - checkDatetimes() bot.resumeExecution = false; bot.multiPeriodProcessDatetime = new Date(bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf()) bot.hasTheBotJustStarted = true @@ -287,11 +299,9 @@ if (process.env.KEY === undefined || process.env.SECRET === undefined) { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> startFordwardTesting -> Key name or Secret not provided, not possible to run the process in Forward Testing mode."); } console.log("Key 'codeName' or 'secret' not provided. Plese check that and try again.") - return + return false } - bot.startMode = "Live" - checkDatetimes() bot.resumeExecution = false; bot.multiPeriodProcessDatetime = new Date(bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf()) bot.hasTheBotJustStarted = true @@ -304,14 +314,14 @@ balancePercentage = bot.SESSION.config.balancePercentage } - bot.VALUES_TO_USE.initialBalanceA = bot.VALUES_TO_USE.initialBalanceA * balancePercentage / 100 - bot.VALUES_TO_USE.initialBalanceB = bot.VALUES_TO_USE.initialBalanceB * balancePercentage / 100 + bot.SESSION.parameters.sessionBaseAsset.config.initialBalance = bot.SESSION.parameters.sessionBaseAsset.config.initialBalance * balancePercentage / 100 + bot.SESSION.parameters.sessionQuotedAsset.config.initialBalance = bot.SESSION.parameters.sessionQuotedAsset.config.initialBalance * balancePercentage / 100 - bot.VALUES_TO_USE.minimumBalanceA = bot.VALUES_TO_USE.minimumBalanceA * balancePercentage / 100 - bot.VALUES_TO_USE.minimumBalanceB = bot.VALUES_TO_USE.minimumBalanceB * balancePercentage / 100 + bot.SESSION.parameters.sessionBaseAsset.config.minimumBalance = bot.SESSION.parameters.sessionBaseAsset.config.minimumBalance * balancePercentage / 100 + bot.SESSION.parameters.sessionQuotedAsset.config.minimumBalance = bot.SESSION.parameters.sessionQuotedAsset.config.minimumBalance * balancePercentage / 100 - bot.VALUES_TO_USE.maximumBalanceA = bot.VALUES_TO_USE.maximumBalanceA * balancePercentage / 100 - bot.VALUES_TO_USE.maximumBalanceB = bot.VALUES_TO_USE.maximumBalanceB * balancePercentage / 100 + bot.SESSION.parameters.sessionBaseAsset.config.maximumBalance = bot.SESSION.parameters.sessionBaseAsset.config.maximumBalance * balancePercentage / 100 + bot.SESSION.parameters.sessionQuotedAsset.config.maximumBalance = bot.SESSION.parameters.sessionQuotedAsset.config.maximumBalance * balancePercentage / 100 pProcessConfig.normalWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame) @@ -319,13 +329,11 @@ } function startPaperTrading(message) { - bot.startMode = "Backtest" - checkDatetimes() bot.resumeExecution = false; bot.hasTheBotJustStarted = true bot.multiPeriodProcessDatetime = new Date(bot.SESSION.parameters.timeRange.config.initialDatetime.valueOf()) - pProcessConfig.normalWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame) + pProcessConfig.normalWaitTime = getTimeFrameFromLabel(bot.SESSION.parameters.timeFrame.label) return true } @@ -350,271 +358,6 @@ } } - function setValuesToUse(message) { - - /* Session Type Dependant Default Values */ - - switch (bot.SESSION.type) { - case 'Backtesting Session': { - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date((new Date()).valueOf() - ONE_YEAR_IN_MILISECONDS) - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date() - break - } - case 'Live Trading Session': { - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) - break - } - case 'Fordward Testing Session': { - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) - break - } - case 'Paper Trading Session': { - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date() - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date((new Date()).valueOf() + ONE_YEAR_IN_MILISECONDS) - break - } - } - - let tradingSystem = bot.TRADING_SYSTEM - - if (tradingSystem !== undefined) { - - /* Applying Session Level Parameters */ - if (bot.SESSION !== undefined) { - if (bot.SESSION.parameters !== undefined) { - - /* Base Asset and Initial Balances. */ - { - if (bot.SESSION.parameters.baseAsset !== undefined) { - if (bot.SESSION.parameters.baseAsset.referenceParent !== undefined) { - if (bot.SESSION.parameters.baseAsset.referenceParent.referenceParent !== undefined) { - - let config = bot.SESSION.parameters.baseAsset.referenceParent.referenceParent.config - - if (config.codeName !== undefined) { - bot.VALUES_TO_USE.baseAsset = config.codeName; - } - - config = bot.SESSION.parameters.baseAsset.config - - if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) { - if (config.initialBalance !== undefined) { - bot.VALUES_TO_USE.initialBalanceA = config.initialBalance; - bot.VALUES_TO_USE.initialBalanceB = 0 - } - if (config.minimumBalance !== undefined) { - bot.VALUES_TO_USE.minimumBalanceA = config.minimumBalance; - bot.VALUES_TO_USE.minimumBalanceB = 0 - } - if (config.maximumBalance !== undefined) { - bot.VALUES_TO_USE.maximumBalanceA = config.maximumBalance; - bot.VALUES_TO_USE.maximumBalanceB = 0 - } - } else { - if (config.initialBalance !== undefined) { - bot.VALUES_TO_USE.initialBalanceB = config.initialBalance; - bot.VALUES_TO_USE.initialBalanceA = 0 - } - if (config.minimumBalance !== undefined) { - bot.VALUES_TO_USE.minimumBalanceB = config.minimumBalance; - bot.VALUES_TO_USE.minimumBalanceA = 0 - } - if (config.maximumBalance !== undefined) { - bot.VALUES_TO_USE.maximumBalanceB = config.maximumBalance; - bot.VALUES_TO_USE.maximumBalanceA = 0 - } - } - - /* Solve when values are missing. */ - if (bot.VALUES_TO_USE.minimumBalanceA === undefined) { - bot.VALUES_TO_USE.minimumBalanceA = 0 - } - - if (bot.VALUES_TO_USE.minimumBalanceB === undefined) { - bot.VALUES_TO_USE.minimumBalanceB = 0 - } - - if (bot.VALUES_TO_USE.maximumBalanceA === undefined) { - bot.VALUES_TO_USE.maximumBalanceA = 10000000000000000 - } - - if (bot.VALUES_TO_USE.maximumBalanceB === undefined) { - bot.VALUES_TO_USE.maximumBalanceB = 10000000000000000 - } - } - } - } - } - - /* Quoted Asset. */ - { - if (bot.SESSION.parameters.quotedAsset !== undefined) { - if (bot.SESSION.parameters.quotedAsset.referenceParent !== undefined) { - if (bot.SESSION.parameters.quotedAsset.referenceParent.referenceParent !== undefined) { - - let config = bot.SESSION.parameters.quotedAsset.referenceParent.referenceParent.config - - if (config.codeName !== undefined) { - bot.VALUES_TO_USE.quotedAsset = config.codeName; - } - } - } - } - } - - /* Time Frame */ - if (bot.SESSION.parameters.timeFrame !== undefined) { - bot.VALUES_TO_USE.timeFrame = bot.SESSION.parameters.timeFrame.config.value - } - - /* Slippage */ - if (bot.SESSION.parameters.slippage !== undefined) { - if (bot.SESSION.parameters.slippage.config !== undefined) { - - let config = bot.SESSION.parameters.slippage.config - - if (config.positionRate !== undefined) { - bot.VALUES_TO_USE.slippage.positionRate = config.positionRate - } - if (config.stopLoss !== undefined) { - bot.VALUES_TO_USE.slippage.stopLoss = config.stopLoss - } - if (config.takeProfit !== undefined) { - bot.VALUES_TO_USE.slippage.takeProfit = config.takeProfit - } - } - } - - /* Fee Structure */ - if (bot.SESSION.parameters.feeStructure !== undefined) { - if (bot.SESSION.parameters.feeStructure.config !== undefined) { - - let config = bot.SESSION.parameters.feeStructure.config - - if (config.maker !== undefined) { - bot.VALUES_TO_USE.feeStructure.maker = config.maker - } - if (config.taker !== undefined) { - bot.VALUES_TO_USE.feeStructure.taker = config.taker - } - } - } - - /* Time Range */ - if (bot.SESSION.parameters.timeRange !== undefined) { - if (bot.SESSION.parameters.timeRange.config !== undefined) { - - let config = bot.SESSION.parameters.timeRange.config - if (config.initialDatetime !== undefined) { - if (isNaN(Date.parse(config.initialDatetime)) === true) { - parentLogger.write(MODULE_NAME, "[WARN] initialize -> runSession -> setValuesToUse -> Cannot use initialDatatime provided at Session Parameters because it is not a valid Date."); - } else { - bot.SESSION.parameters.timeRange.config.initialDatetime = new Date(config.initialDatetime) - } - } - if (config.finalDatetime !== undefined) { - if (isNaN(Date.parse(config.finalDatetime)) === true) { - parentLogger.write(MODULE_NAME, "[WARN] initialize -> runSession -> setValuesToUse -> Cannot use finalDatetime provided at Session Parameters because it is not a valid Date."); - } else { - bot.SESSION.parameters.timeRange.config.finalDatetime = new Date(config.finalDatetime) - } - } - } - } - } - } - } - } - - function initializeSocialBots() { - - if (bot.SESSION.socialBots !== undefined) { - if (bot.SESSION.socialBots.bots !== undefined) { - for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { - let socialBot = bot.SESSION.socialBots.bots[i] - if (socialBot.type === "Telegram Bot") { - let config = socialBot.config - socialBot.botInstance = initializeTelegramBot(config.botToken, config.chatId) - } - } - } - - function announce(announcement) { - if (bot.SESSION.socialBots.bots !== undefined) { - for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { - let socialBot = bot.SESSION.socialBots.bots[i] - try { - let config = announcement.config - - if (socialBot.type === "Telegram Bot") { - if (announcement.formulaValue !== undefined) { - socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err)) - } else { - socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, config.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err)) - } - } - - } catch (err) { - parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> err = " + err.stack); - } - } - } - } - - bot.SESSION.socialBots.announce = announce - } - } - - function finalizeSocialBots() { - if (bot.SESSION.socialBots === undefined) { return } - if (bot.SESSION.socialBots.bots !== undefined) { - for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { - let socialBot = bot.SESSION.socialBots.bots[i] - if (socialBot.type === "Telegram Bot") { - let config = socialBot.config - socialBot.botInstance = finalizeTelegramBot(config.chatId) - } - } - } - } - - function initializeTelegramBot(botToken, chatId) { - /* Telegram Bot Initialization */ - try { - const Telegraf = require('telegraf') - let telegramBot - telegramBot = new Telegraf(botToken) - telegramBot.start((ctx) => ctx.reply('Hi! I am the Telegram Bot that will tell you what happens with your trading session.')) - telegramBot.help((ctx) => ctx.reply('I can stop the session if you say STOP.')) - telegramBot.hears('STOP', (ctx) => stopSession()) - telegramBot.launch() - - const Telegram = require('telegraf/telegram') - - telegramAPI = new Telegram(botToken) - - const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "." - telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err)) - - let botInstance = { - telegramBot: telegramBot, - telegramAPI: telegramAPI, - chatId: chatId - } - return botInstance - } catch (err) { - parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> err = " + err.stack); - } - - } - - function finalizeTelegramBot(chatId) { - const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped." - telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err)) - } - } catch (err) { parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); diff --git a/SocialBots.js b/SocialBots.js new file mode 100644 index 000000000..742a8976b --- /dev/null +++ b/SocialBots.js @@ -0,0 +1,80 @@ +exports.newSocialBots = function newSocialBots(bot, logger) { + + const MODULE_NAME = 'Social Bots' + + let thisObject = { + sendMessage: sendMessage, + initialize: initialize, + finalize: finalize + } + + const TELEGRAM_BOT_MODULE = require('./TelegramBot.js') + + return thisObject + + function initialize() { + if (bot.SESSION.socialBots !== undefined) { + if (bot.SESSION.socialBots.bots !== undefined) { + for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { + let socialBot = bot.SESSION.socialBots.bots[i] + if (socialBot.type === "Telegram Bot") { + let config = socialBot.config + socialBot.botInstance = SOCIAL_BOTS_MODULE.newTelegramBot(bot, logger) + socialBot.botInstance.initialize(config.botToken, config.chatId) + } + } + } + + function announce(announcement) { + if (bot.SESSION.socialBots.bots !== undefined) { + for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { + let socialBot = bot.SESSION.socialBots.bots[i] + try { + let config = announcement.config + + if (socialBot.type === "Telegram Bot") { + if (announcement.formulaValue !== undefined) { + socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err)) + } else { + socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, config.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err)) + } + } + + } catch (err) { + parentLogger.write(MODULE_NAME, "[WARN] initialize -> announce -> err = " + err.stack); + } + } + } + } + + bot.SESSION.socialBots.announce = announce + } + } + + function finalize() { + if (bot.SESSION.socialBots === undefined) { return } + if (bot.SESSION.socialBots.bots !== undefined) { + for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { + let socialBot = bot.SESSION.socialBots.bots[i] + if (socialBot.type === "Telegram Bot") { + socialBot.botInstance.finalize() + } + } + } + } + + + + function sendMessage(message) { + if (bot.SESSION.socialBots !== undefined) { + if (bot.SESSION.socialBots.bots !== undefined) { + for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) { + let socialBot = bot.SESSION.socialBots.bots[i] + if (socialBot.type === "Telegram Bot") { + socialBot.botInstance.sendMessage(message) + } + } + } + } + } +} \ No newline at end of file diff --git a/TelegramBot.js b/TelegramBot.js new file mode 100644 index 000000000..d0677c46d --- /dev/null +++ b/TelegramBot.js @@ -0,0 +1,51 @@ +exports.newTelegramBot = function newTelegramBot(bot, logger) { + + const MODULE_NAME = 'Telegram Bot' + + let thisObject = { + telegramBot: undefined, + telegramAPI: undefined, + chatId: undefined, + sendMessage: sendMessage, + initialize: initialize, + finalize: finalize + } + + return thisObject + + function initialize(botToken, chatId) { + /* Telegram Bot Initialization */ + try { + thisObject.chatId = chatId + + const Telegraf = require('telegraf') + + thisObject.telegramBot = new Telegraf(botToken) + thisObject.telegramBot.start((ctx) => ctx.reply('Hi! I am the Telegram Bot that will tell you what happens with your trading session.')) + thisObject.telegramBot.help((ctx) => ctx.reply('I can stop the session if you type STOP.')) + thisObject.telegramBot.hears('STOP', (ctx) => bot.SESSION.stop(' by STOP command at Telegram.')) + thisObject.telegramBot.launch() + + const Telegram = require('telegraf/telegram') + + thisObject.telegramAPI = new Telegram(botToken) + + const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "." + thisObject.telegramAPI.sendMessage(thisObject.chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initializeTelegramBot -> Telegram API error -> err = " + err)) + + } catch (err) { + parentLogger.write(MODULE_NAME, "[WARN] initialize -> err = " + err.stack); + } + + } + + function finalize() { + const messge = "I have been ordered to shut down. Goodbye!" + telegramAPI.sendMessage(thisObject.chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] finalize -> Telegram API error -> err = " + err)) + } + + function sendMessage(message) { + thisObject.telegramAPI.sendMessage(thisObject.chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] announce -> Telegram API error -> err = " + err)) + } + +} \ No newline at end of file diff --git a/Trading/Snapshots.js b/Trading/Snapshots.js index 7edfd34f9..49faa2995 100644 --- a/Trading/Snapshots.js +++ b/Trading/Snapshots.js @@ -76,7 +76,6 @@ exports.newSnapshots = function newSnapshots(bot, logger) { } } - snapshots.triggerOn.push(closeValues.concat(snapshots.lastTriggerOn)) snapshots.takePosition.push(closeValues.concat(snapshots.lastTakePosition)) diff --git a/Trading/TradingExecution.js b/Trading/TradingExecution.js index 2df00a402..4aa191a79 100644 --- a/Trading/TradingExecution.js +++ b/Trading/TradingExecution.js @@ -27,8 +27,8 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) { /* Check if we need to execute. */ if (currentCandleIndex > candles.length - 10) { /* Only at the last candles makes sense to check if we are in live mode or not. */ /* Check that we are in LIVE MODE */ - if (bot.startMode === 'Live') { - logger.write(MODULE_NAME, '[PERSIST] runSimulation -> loop -> takePositionNow -> Taking a Position in Live Mode.') + if (bot.SESSION.type === 'Live Trading Session' || bot.SESSION.type === 'Fordward Testion Session') { + logger.write(MODULE_NAME, '[PERSIST] runSimulation -> loop -> takePositionNow -> Taking a Position in ' + bot.SESSION.type) logger.write(MODULE_NAME, '[PERSIST] runSimulation -> loop -> takePositionNow -> tradingEngine.current.position.size.value = ' + tradingEngine.current.position.size.value) logger.write(MODULE_NAME, '[PERSIST] runSimulation -> loop -> takePositionNow -> tradingEngine.current.position.rate.value = ' + tradingEngine.current.position.rate.value) logger.write(MODULE_NAME, '[PERSIST] runSimulation -> loop -> takePositionNow -> slippageAmount = ' + slippageAmount) @@ -201,7 +201,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) { function closePosition() { if (currentCandleIndex > candles.length - 10) { /* Only at the last candles makes sense to check if we are in live mode or not. */ /* Check that we are in LIVE MODE */ - if (bot.startMode === 'Live') { + if (bot.SESSION.type === 'Live Trading Session' || bot.SESSION.type === 'Fordward Testion Session') { /* We see if we need to put the actual order at the exchange. */ if (variable.executionContext !== undefined) { switch (variable.executionContext.status) { diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 579de4f33..73264fec4 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -13,7 +13,7 @@ const MULTI_PERIOD = require(ROOT_DIR + 'MultiPeriod'); const FILE_STORAGE = require('./FileStorage.js'); const SESSION = require(ROOT_DIR + 'Session'); - + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); let session = SESSION.newSession(bot, parentLogger) @@ -87,7 +87,7 @@ USER_BOT_COMMONS = {} USER_BOT_COMMONS.newCommons = eval(text); // Use this for production - session.initialize(onSessionInitialized) + session.initialize(onSessionInitialized) function onSessionInitialized(err) { callBackFunction(err); @@ -95,7 +95,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -117,7 +117,7 @@ try { - processHeartBeat(undefined, undefined, "Running...") + processHeartBeat(undefined, undefined, "Running...") function pad(str, max) { str = str.toString(); return str.length < max ? pad(" " + str, max) : str; @@ -142,7 +142,7 @@ /* Heartbeats sent to the UI */ bot.sessionHeartBeat = sessionHeartBeat bot.processHeartBeat = processHeartBeat - processHeartBeat() + processHeartBeat() /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ @@ -153,7 +153,7 @@ const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies'); const DATA_SET = require(ROOT_DIR + 'DataSet'); const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents'); - const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput'); + const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput'); /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ @@ -178,7 +178,7 @@ /* Checking if we should process this loop or not.*/ if (bot.STOP_SESSION === true) { - + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Waiting for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be ran."); } console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) @@ -408,7 +408,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -419,7 +419,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -484,7 +484,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -495,7 +495,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -578,7 +578,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -589,7 +589,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -667,7 +667,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -678,7 +678,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -775,7 +775,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -786,7 +786,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = "+ err.stack); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -910,7 +910,7 @@ switch (nextWaitTime) { case 'Normal': { let waitTime - if (bot.startMode === "Live") { + if (bot.SESSION.type === 'Live Trading Session' || bot.SESSION.type === 'Fordward Testion Session') { waitTime = processConfig.liveWaitTime } else { waitTime = processConfig.normalWaitTime @@ -939,21 +939,21 @@ checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.deadWaitTime, bot.loopCounter); } nextLoopTimeoutHandle = setTimeout(loop, processConfig.retryWaitTime); - processHeartBeat(undefined, undefined, "Trying to recover from some problem. Waiting " + processConfig.retryWaitTime / 1000 + " seconds for next execution.") + processHeartBeat(undefined, undefined, "Trying to recover from some problem. Waiting " + processConfig.retryWaitTime / 1000 + " seconds for next execution.") logger.persist(); } break; case 'Sleep': { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.sleepWaitTime / 60000) + " minutes."); } nextLoopTimeoutHandle = setTimeout(loop, processConfig.sleepWaitTime); - processHeartBeat(undefined, undefined, "Waiting " + processConfig.sleepWaitTime / 60000 + " minutes for next execution.") + processHeartBeat(undefined, undefined, "Waiting " + processConfig.sleepWaitTime / 60000 + " minutes for next execution.") logger.persist(); } break; case 'Coma': { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.comaWaitTime / 3600000) + " hours."); } nextLoopTimeoutHandle = setTimeout(loop, processConfig.comaWaitTime); - processHeartBeat(undefined, undefined, "Waiting " + processConfig.comaWaitTime / 3600000 + " hours for next execution.") + processHeartBeat(undefined, undefined, "Waiting " + processConfig.comaWaitTime / 3600000 + " hours for next execution.") logger.persist(); } break; @@ -1017,7 +1017,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err.stack); + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); @@ -1060,7 +1060,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err.stack); + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = " + err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle);