diff --git a/Commons.js b/Commons.js index d9a660921..d139ebd3e 100644 --- a/Commons.js +++ b/Commons.js @@ -65,6 +65,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Entering function."); } + let executionArray = []; let recordsArray = []; let conditionsArray = []; let strategiesArray = []; @@ -893,7 +894,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (passed) { - type = '"Sell"'; + type = '"Take Position"'; strategyStage = 'Open Stage'; stopLossStage = 'Open Stage'; @@ -1153,7 +1154,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } marketRate = stopLoss; - type = '"Buy@StopLoss"'; + type = '"Close@StopLoss"'; strategyStage = 'Close Stage'; stopLossStage = 'No Stage'; takeProfitStage = 'No Stage'; @@ -1189,7 +1190,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } marketRate = takeProfit; - type = '"Buy@TakeProfit"'; + type = '"Close@TakeProfit"'; strategyStage = 'Close Stage'; stopLossStage = 'No Stage'; takeProfitStage = 'No Stage'; @@ -1380,21 +1381,25 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let messageType; let message; let simulationRecord; - let orderRecord; + let executionRecord; + let executionMessage; messageId++; - if (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') { + if (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage' || type === '"Close@TakeProfit"' || type === '"Close@StopLoss"') { - if (strategyStage === 'Open Stage') { + if (type === '"Take Position"') { messageType = MESSAGE_TYPE.Order; orderId++; - } - if (strategyStage === 'Manage Stage') { - messageType = MESSAGE_TYPE.OrderUpdate; + } else { + if (type === '"Close@TakeProfit"' || type === '"Close@StopLoss"') { + messageType = MESSAGE_TYPE.OrderUpdate; + } else { + messageType = MESSAGE_TYPE.OrderUpdate; + } } - orderRecord = createMessage( + executionMessage = createMessage( messageId, MESSAGE_ENTITY.SimulationEngine, MESSAGE_ENTITY.SimulationExecutor, @@ -1420,7 +1425,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } else { - orderRecord = createMessage( + executionMessage = createMessage( messageId, MESSAGE_ENTITY.SimulationEngine, MESSAGE_ENTITY.SimulationExecutor, @@ -1444,6 +1449,14 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { "") } + executionRecord = { + begin: candle.begin, + end: candle.end, + executionRecord: executionMessage + } + + executionArray.push(executionRecord) + let strategyStageNumber switch (strategyStage) { case 'No Stage': { @@ -1504,7 +1517,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { takeProfit: takeProfit, stopLossPhase: stopLossPhase, takeProfitPhase: takeProfitPhase, - orderRecord: orderRecord, + executionRecord: executionMessage, positionSize: positionSize, initialBalanceA: initialBalanceA, minimumBalanceA: minimumBalanceA, @@ -1605,7 +1618,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> callback -> recordsArray.length = " + recordsArray.length); } - callback(tradingSystem, recordsArray, conditionsArray, strategiesArray, tradesArray, lastObjectsArray); + callback(tradingSystem, executionArray, recordsArray, conditionsArray, strategiesArray, tradesArray, lastObjectsArray); function getElement(pArray, begin, end) { @@ -1653,17 +1666,17 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (previous !== undefined) { - if (previous._15 > LRC._15) { LRC.direction15 = 'down'; } - if (previous._15 < LRC._15) { LRC.direction15 = 'up'; } - if (previous._15 === LRC._15) { LRC.direction15 = 'side'; } + if (previous._15 > LRC._15) { LRC.direction15 = 'Down'; } + if (previous._15 < LRC._15) { LRC.direction15 = 'Up'; } + if (previous._15 === LRC._15) { LRC.direction15 = 'Side'; } - if (previous._30 > LRC._30) { LRC.direction30 = 'down'; } - if (previous._30 < LRC._30) { LRC.direction30 = 'up'; } - if (previous._30 === LRC._30) { LRC.direction30 = 'side'; } + if (previous._30 > LRC._30) { LRC.direction30 = 'Down'; } + if (previous._30 < LRC._30) { LRC.direction30 = 'Up'; } + if (previous._30 === LRC._30) { LRC.direction30 = 'Side'; } - if (previous._60 > LRC._60) { LRC.direction60 = 'down'; } - if (previous._60 < LRC._60) { LRC.direction60 = 'up'; } - if (previous._60 === LRC._60) { LRC.direction60 = 'side'; } + if (previous._60 > LRC._60) { LRC.direction60 = 'Down'; } + if (previous._60 < LRC._60) { LRC.direction60 = 'Up'; } + if (previous._60 === LRC._60) { LRC.direction60 = 'Side'; } } @@ -1700,9 +1713,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (previous !== undefined) { - if (previous.movingAverage > percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'down'; } - if (previous.movingAverage < percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'up'; } - if (previous.movingAverage === percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'side'; } + if (previous.movingAverage > percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Down'; } + if (previous.movingAverage < percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Up'; } + if (previous.movingAverage === percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Side'; } } @@ -1739,9 +1752,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (previous !== undefined) { - if (previous.movingAverage > bollingerBand.movingAverage) { bollingerBand.direction = 'down'; } - if (previous.movingAverage < bollingerBand.movingAverage) { bollingerBand.direction = 'up'; } - if (previous.movingAverage === bollingerBand.movingAverage) { bollingerBand.direction = 'side'; } + if (previous.movingAverage > bollingerBand.movingAverage) { bollingerBand.direction = 'Down'; } + if (previous.movingAverage < bollingerBand.movingAverage) { bollingerBand.direction = 'Up'; } + if (previous.movingAverage === bollingerBand.movingAverage) { bollingerBand.direction = 'Side'; } } @@ -1856,9 +1869,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { candle.begin = dataFile[i][4]; candle.end = dataFile[i][5]; - if (candle.open > candle.close) { candle.direction = 'down'; } - if (candle.open < candle.close) { candle.direction = 'up'; } - if (candle.open === candle.close) { candle.direction = 'side'; } + if (candle.open > candle.close) { candle.direction = 'Down'; } + if (candle.open < candle.close) { candle.direction = 'Up'; } + if (candle.open === candle.close) { candle.direction = 'Side'; } candle.previous = previous; diff --git a/Multi-Period-Daily/User.Bot.js b/Multi-Period-Daily/User.Bot.js index 2b249a0d0..94f18bbe3 100644 --- a/Multi-Period-Daily/User.Bot.js +++ b/Multi-Period-Daily/User.Bot.js @@ -5,6 +5,7 @@ const MODULE_NAME = "User Bot"; + const EXECUTION_FOLDER_NAME = "Trading-Execution"; const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation"; const CONDITIONS_FOLDER_NAME = "Simulation-Conditions"; const STRATEGIES_FOLDER_NAME = "Simulation-Strategies"; @@ -104,16 +105,91 @@ writeFiles, callBackFunction) - function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pLastObjectsArray) { + function writeFiles(pTradingSystem, pExecutionArray, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pLastObjectsArray) { tradingSystem = pTradingSystem + executionArray = pExecutionArray recordsArray = pRecordsArray conditionsArray = pConditionsArray strategiesArray = pStrategiesArray tradesArray = pTradesArray lastObjectsArray = pLastObjectsArray - writeRecordsFile() + writeExecutionFile() + } + + function writeExecutionFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < executionArray.length; i++) { + + let record = executionArray[i]; + + /* Will only add to the file the records of the current day */ + + if (record.begin < currentDay.valueOf()) { continue; } + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + JSON.stringify(record.executionRecord) + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + EXECUTION_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeRecordsFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } } function writeRecordsFile() { @@ -161,7 +237,7 @@ record.takeProfit + "," + record.stopLossPhase + "," + record.takeProfitPhase + "," + - JSON.stringify(record.orderRecord) + "," + + JSON.stringify(record.executionRecord) + "," + record.positionSize + "," + record.initialBalanceA + "," + record.minimumBalanceA + "," + diff --git a/Multi-Period-Market/User.Bot.js b/Multi-Period-Market/User.Bot.js index 2631be8e9..5e031fcb5 100644 --- a/Multi-Period-Market/User.Bot.js +++ b/Multi-Period-Market/User.Bot.js @@ -5,6 +5,7 @@ const MODULE_NAME = "User Bot"; + const EXECUTION_FOLDER_NAME = "Trading-Execution"; const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation"; const CONDITIONS_FOLDER_NAME = "Simulation-Conditions"; const STRATEGIES_FOLDER_NAME = "Simulation-Strategies"; @@ -104,16 +105,86 @@ writeFiles, callBackFunction) - function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pLastObjectsArray) { + function writeFiles(pTradingSystem, pExecutionArray, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pLastObjectsArray) { tradingSystem = pTradingSystem + executionArray = pExecutionArray recordsArray = pRecordsArray conditionsArray = pConditionsArray strategiesArray = pStrategiesArray tradesArray = pTradesArray lastObjectsArray = pLastObjectsArray - writeRecordsFile() + writeExecutionFile() + } + + function writeExecutionFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < executionArray.length; i++) { + + let record = executionArray[i]; + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + JSON.stringify(record.executionRecord) + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + EXECUTION_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + outputPeriodLabel; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeRecordsFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } } function writeRecordsFile() { @@ -157,7 +228,7 @@ record.takeProfit + "," + record.stopLossPhase + "," + record.takeProfitPhase + "," + - JSON.stringify(record.orderRecord) + "," + + JSON.stringify(record.executionRecord) + "," + record.positionSize + "," + record.initialBalanceA + "," + record.minimumBalanceA + "," +