diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/social-bot-command.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/social-bot-command.svg
new file mode 100644
index 000000000..f99bd7c9c
--- /dev/null
+++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/social-bot-command.svg
@@ -0,0 +1,182 @@
+
+
diff --git a/Projects/Superalgos/Icons/social-bot-command.png b/Projects/Superalgos/Icons/social-bot-command.png
new file mode 100644
index 000000000..0318ce9ae
Binary files /dev/null and b/Projects/Superalgos/Icons/social-bot-command.png differ
diff --git a/Projects/Superalgos/Schemas/App-Schema/formula.json b/Projects/Superalgos/Schemas/App-Schema/formula.json
index 899eb3258..5acb5a1e1 100644
--- a/Projects/Superalgos/Schemas/App-Schema/formula.json
+++ b/Projects/Superalgos/Schemas/App-Schema/formula.json
@@ -28,7 +28,7 @@
},
"level": 4,
"attachingRules": {
- "compatibleTypes": "->Target Size In Base Asset->Target Size In Quoted Asset->Target Rate->Phase->Simulated Actual Rate->Situation->Indicator Function->Order Rate->"
+ "compatibleTypes": "->Target Size In Base Asset->Target Size In Quoted Asset->Target Rate->Phase->Simulated Actual Rate->Situation->Indicator Function->Order Rate->Social Bot Command->"
},
"propertyNameAtParent": "formula"
}
\ No newline at end of file
diff --git a/Projects/Superalgos/Schemas/App-Schema/social-bot-command.json b/Projects/Superalgos/Schemas/App-Schema/social-bot-command.json
new file mode 100644
index 000000000..dd25f533a
--- /dev/null
+++ b/Projects/Superalgos/Schemas/App-Schema/social-bot-command.json
@@ -0,0 +1,49 @@
+{
+ "type": "Social Bot Command",
+ "editors": {
+ "config": true
+ },
+ "menuItems": [
+ {
+ "action": "Configure",
+ "actionFunction": "uiObject.configEditor.activate",
+ "label": "Configure",
+ "iconPathOn": "configuration",
+ "iconPathOff": "configuration"
+ },
+ {
+ "action": "Add UI Object",
+ "disableIfPropertyIsDefined": true,
+ "propertyToCheckFor": "formula",
+ "label": "Add Formula",
+ "relatedUiObject": "Formula",
+ "actionFunction": "payload.executeAction"
+ },
+ {
+ "action": "Delete UI Object",
+ "askConfirmation": true,
+ "confirmationLabel": "Confirm to Delete",
+ "label": "Delete",
+ "iconPathOn": "delete-entity",
+ "iconPathOff": "delete-entity",
+ "actionFunction": "payload.executeAction"
+ }
+ ],
+ "initialValues": {
+ "config": "{ \n\"name\": \"Enter the name of the command without a leading slash\"\n}"
+ },
+ "addLeftIcons": true,
+ "level": 4,
+ "attachingRules": {
+ "compatibleTypes": "->Telegram Bot->"
+ },
+ "childrenNodesProperties": [
+ {
+ "name": "formula",
+ "type": "node",
+ "childType": "Formula",
+ "autoAdd": true
+ }
+ ],
+ "propertyNameAtParent": "socialBotCommand"
+}
diff --git a/Projects/Superalgos/Schemas/App-Schema/telegram-bot.json b/Projects/Superalgos/Schemas/App-Schema/telegram-bot.json
index 6a9829a18..809452173 100644
--- a/Projects/Superalgos/Schemas/App-Schema/telegram-bot.json
+++ b/Projects/Superalgos/Schemas/App-Schema/telegram-bot.json
@@ -11,6 +11,12 @@
"iconPathOn": "configuration",
"iconPathOff": "configuration"
},
+ {
+ "action": "Add UI Object",
+ "label": "Add Social Bot Command",
+ "relatedUiObject": "Social Bot Command",
+ "actionFunction": "payload.executeAction"
+ },
{
"action": "Send Telegram Test Message",
"label": "Send Telegram Test Message",
@@ -36,6 +42,13 @@
"attachingRules": {
"compatibleTypes": "->Social Bots->"
},
- "childrenNodesProperties": [],
+ "childrenNodesProperties": [
+ {
+ "name": "socialBotCommand",
+ "type": "array",
+ "childType": "Social Bot Command",
+ "autoAdd": true
+ }
+ ],
"propertyNameAtParent": "telegramBots"
}
\ No newline at end of file
diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/SocialBots.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/SocialBots.js
index fe7736edd..e334380d9 100644
--- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/SocialBots.js
+++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/SocialBots.js
@@ -16,16 +16,15 @@ exports.newSuperalgosBotModulesSocialBots = function (processIndex) {
if (prop.toLowerCase().includes("Bots".toLowerCase())) {
for (let i = 0; i < TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop].length; i++) {
let socialBot = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop][i]
+ let config = socialBot.config
+ let commands = socialBot.socialBotCommand
if (socialBot.type === "Telegram Bot") {
- let config = socialBot.config
socialBot.botInstance = TS.projects.superalgos.botModules.telegramBot.newSuperalgosBotModulesTelegramBot(processIndex)
- socialBot.botInstance.initialize(config.botToken, config.chatId)
+ socialBot.botInstance.initialize(config, commands)
} else if (socialBot.type === "Discord Bot") {
- let config = socialBot.config
socialBot.botInstance = TS.projects.superalgos.botModules.discordBot.newSuperalgosBotModulesDiscordBot(processIndex)
socialBot.botInstance.initialize(config)
} else if (socialBot.type === "Slack Bot") {
- let config = socialBot.config
socialBot.botInstance = TS.projects.superalgos.botModules.slackBot.newSuperalgosBotModulesSlackBot(processIndex)
socialBot.botInstance.initialize(config)
}
diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/TelegramBot.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/TelegramBot.js
index 2d47ba3bc..a5b34f5ed 100644
--- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/TelegramBot.js
+++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Announcements/TelegramBot.js
@@ -14,9 +14,12 @@ exports.newSuperalgosBotModulesTelegramBot = function (processIndex) {
return thisObject
- function initialize(botToken, chatId) {
+ function initialize(config, commands) {
/* Telegram Bot Initialization */
try {
+ let botToken = config.botToken
+ let chatId = config.chatId
+
thisObject.chatId = chatId
const Telegraf = require('telegraf')
@@ -25,16 +28,17 @@ exports.newSuperalgosBotModulesTelegramBot = function (processIndex) {
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.replyWithHTML('SUPERALGOS BOT HELP\n\n' +
'• Use /stop to stop the session.\n' +
- '• Use /help to receive this help message.\n' +
- '• Use /balances for episode balances.\n' +
- '• Use /counters for episode counters.\n' +
- '• Use /statistics for episode statistics.\n' +
- '• Use /uptime for episode uptime.'))
+ '• Use /help to receive this help message.\n\n' +
+ 'Additional commands can be configured using the Social Bot Command node.'))
thisObject.telegramBot.command('stop', (ctx) => TS.projects.superalgos.functionLibraries.sessionFunctions.stopSession(processIndex, 'by command from Telegram.'))
- thisObject.telegramBot.command('balances', (ctx) => interpretCommand('balances', processIndex))
- thisObject.telegramBot.command('uptime', (ctx) => interpretCommand('uptime', processIndex))
- thisObject.telegramBot.command('statistics', (ctx) => interpretCommand('statistics', processIndex))
- thisObject.telegramBot.command('counters', (ctx) => interpretCommand('counters', processIndex))
+
+ /* Set up additional commands for each Social Bot Command node */
+ if(commands !== undefined) {
+ for (let i = 0; i < commands.length; i++) {
+ thisObject.telegramBot.command(commands[i].config.name, (ctx) => interpretCommand(commands[i].formula.code, processIndex))
+ }
+ }
+
thisObject.telegramBot.launch()
const Telegram = require('telegraf/telegram')
@@ -67,72 +71,28 @@ exports.newSuperalgosBotModulesTelegramBot = function (processIndex) {
let message
let tradingEngine
- let tradingEpisode
- let sessionNode
- let sessionName
+ let tradingSystem
+ let sessionParameters
- tradingEngine = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.tradingEngine
- tradingEpisode = tradingEngine.tradingCurrent.tradingEpisode
+ if(TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE !== undefined) {
+ tradingEngine = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.tradingEngine
+ tradingSystem = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.tradingSystem
+ }
+ sessionParameters = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.tradingParameters
- sessionNode = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE
- sessionName = sessionNode.name
+ let taskParameters = {
+ exchange: TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.name,
+ market: TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName +
+ '/' +
+ TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
+ }
-
- switch (command) {
- case 'balances': {
-
- let baseAsset = TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName
- let quotedAsset = TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
-
- message = "SUPERALGOS BALANCES\n\nTrading Session: " + sessionName +
- "\nPair: " + baseAsset + "/" + quotedAsset +
- "\nBase Asset: " + tradingEpisode.episodeBaseAsset.balance.value + " " + baseAsset +
- "\nQuoted Asset: " + tradingEpisode.episodeQuotedAsset.balance.value + " " + quotedAsset
- break
- }
- case 'uptime': {
-
- let sessionBegin = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_BEGIN
-
- let dateBegin = new Date(sessionBegin)
- let dateNow = new Date();
-
- let seconds = Math.floor((dateNow - (dateBegin))/1000)
- let minutes = Math.floor(seconds/60)
- let hours = Math.floor(minutes/60)
- let days = Math.floor(hours/24)
-
- hours = hours-(days*24)
- minutes = minutes-(days*24*60)-(hours*60)
- seconds = seconds-(days*24*60*60)-(hours*60*60)-(minutes*60)
-
- let uptime = days + "D, " + hours + "H, " + minutes + "M, " + seconds + "S"
-
- message = "SUPERALGOS UPTIME\n\nTrading Session: " + sessionName +
- "\nUptime: " + uptime
- break
- }
- case 'statistics': {
-
- message = "SUPERALGOS STATISTICS\n\nTrading Session: " + sessionName +
- "\nDays: " + (tradingEpisode.tradingEpisodeStatistics.days.value).toFixed(2) +
- "\nProfit Loss: " + tradingEpisode.tradingEpisodeStatistics.profitLoss.value +
- "\nROI: " + (tradingEpisode.tradingEpisodeStatistics.ROI.value).toFixed(2) +
- "\nAnnualized Rate Of Return: " + (tradingEpisode.tradingEpisodeStatistics.annualizedRateOfReturn.value).toFixed(2) +
- "\nHit Fail: " + tradingEpisode.tradingEpisodeStatistics.hitFail.value
- break
- }
- case 'counters': {
-
- message = "SUPERALGOS COUNTERS\n\nTrading Session: " + sessionName +
- "\nPeriods: " + tradingEpisode.tradingEpisodeCounters.periods.value +
- "\nStrategies: " + tradingEpisode.tradingEpisodeCounters.strategies.value +
- "\nPositions: " + tradingEpisode.tradingEpisodeCounters.positions.value +
- "\nOrders: " + tradingEpisode.tradingEpisodeCounters.orders.value +
- "\nHits: " + tradingEpisode.tradingEpisodeCounters.hits.value +
- "\nFails: " + tradingEpisode.tradingEpisodeCounters.fails.value
- break
- }
+ try {
+ message = eval(command)
+ } catch (err) {
+ TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_INSTANCE_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
+ "[WARN] interpretCommand -> Telegram API error evaluating user formula -> err = " + err.stack)
+ return
}
thisObject.telegramAPI.sendMessage(thisObject.chatId, message, {parse_mode: 'HTML'}).catch(err => TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_INSTANCE_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
diff --git a/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js b/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js
index d70d32fb5..f59315da3 100644
--- a/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js
+++ b/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js
@@ -156,6 +156,7 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() {
'Trading Parameters->' +
'Session Base Asset->Session Quoted Asset->Time Range->Time Frame->Slippage->Fee Structure->Snapshots->Heartbeats->User Defined Parameters->' +
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->' +
+ 'Social Bot Command->Formula->' +
'Exchange Account Asset->Asset->'
let session = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)