diff --git a/src/schema/queries/FileContent.js b/src/schema/queries/FileContent.js index 63a9164a8..43bf10c3d 100644 --- a/src/schema/queries/FileContent.js +++ b/src/schema/queries/FileContent.js @@ -16,6 +16,7 @@ const resolve = async (parent, { file }, context) => { let host = await getDevTeamHost(file.container, file.accessKey) if (host === undefined || host === null) { + logger.error('Error getting file:' + JSON.stringify(file)) throw new AuthenticationError() } diff --git a/src/storage/templates/Simulator/Commons.js b/src/storage/templates/Simulator/Commons.js index f96787ff9..cb6a0f0e8 100644 --- a/src/storage/templates/Simulator/Commons.js +++ b/src/storage/templates/Simulator/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 = []; @@ -183,8 +184,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* Simulation Records */ - let positionRate = 0; - let positionSize = 0; + let tradePositionRate = 0; + let tradePositionSize = 0; let positionInstant; let previousBalanceAssetA = 0; @@ -341,36 +342,56 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { for (let i = 0; i < candles.length; i++) { - /* Update all the data objects available for the simulation. */ let candle = candles[i]; let percentageBandwidth = percentageBandwidthMap.get(candle.begin); let bollingerBand = bollingerBandsMap.get(candle.begin); + let bollingerChannel = getElement(bollingerChannelsArray, candle.begin, candle.end); + let bollingerSubChannel = getElement(bollingerSubChannelsArray, candle.begin, candle.end); + //let LRC = LRCMap.get(candle.begin); - //if (LRC === undefined) { continue; } - if (percentageBandwidth === undefined) { continue; } // percentageBandwidth might start after the first few candles. + /* If any of the needed indicators is missing, then that period is not calculated */ + if (candle.begin < initialDate.valueOf()) { continue; } + if (bollingerBand === undefined) { continue; } + if (percentageBandwidth === undefined) { continue; } // percentageBandwidth might start after the first few candles. + if (bollingerChannel === undefined) { continue; } + if (bollingerSubChannel === undefined) { continue; } + + //if (LRC === undefined) { continue; } periods++; days = periods * timePeriod / ONE_DAY_IN_MILISECONDS; - if (currentDay !== undefined) { + if (currentDay !== undefined) { // This means that we are processing Daily Files if (candle.end < currentDay.valueOf()) { yesterday.Periods++; } - } - let channel = getElement(bollingerChannelsArray, candle.begin, candle.end); - let subChannel = getElement(bollingerSubChannelsArray, candle.begin, candle.end); + /* We skip the candle at the head of the market because i has not closed yet. */ + let candlesPerDay = ONE_DAY_IN_MILISECONDS / timePeriod + if (i === candles.length - 1) { + if ((candles.length < candlesPerDay) || (candles.length > candlesPerDay && candles.length < candlesPerDay * 2) ) { + /*We are at the head of the market, thus we skip the last candle because it has not close yet. */ + continue; + /* Note here that in the last candle of the first day or the second day it will use an incomplete candle and partially calculated indicators. + if we skip these two periods, then there will be a hole in the file since the last period will be missing. */ + } + } + } else { // We are processing Market Files + if (i === candles.length - 1) { + continue; + } + } let lastObjects = { candle: clone(candle), //LRC: clone(LRC), bollingerBand: clone(bollingerBand), percentageBandwidth: clone(percentageBandwidth), - channel: clone(channel), - subChannel: clone(subChannel) + bollingerChannel: clone(bollingerChannel), + bollingerSubChannel: clone(bollingerSubChannel) } function clone(obj) { @@ -386,8 +407,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { //lastObjects.LRC.previous = undefined; lastObjects.bollingerBand.previous = undefined; lastObjects.percentageBandwidth.previous = undefined; - lastObjects.channel.previous = undefined; - lastObjects.subChannel.previous = undefined; + lastObjects.bollingerChannel.previous = undefined; + lastObjects.bollingerSubChannel.previous = undefined; lastObjectsArray.push(lastObjects); @@ -415,6 +436,11 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let strategy = tradingSystem.strategies[j]; + let positionSize = 0 + let positionRate = 0 + + /* Continue with the rest of the formulas and conditions */ + let triggerStage = strategy.triggerStage if (triggerStage !== undefined) { @@ -478,10 +504,67 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (openStage !== undefined) { + /* Default Values*/ + if (baseAsset === 'BTC') { + positionSize = balanceAssetA; + positionRate = candle.close; + } else { + positionSize = balanceAssetB; + positionRate = candle.close; + } + let initialDefinition = openStage.initialDefinition if (initialDefinition !== undefined) { + if (tradePositionSize !== 0) { + positionSize = tradePositionSize + } else { + if (initialDefinition.positionSize !== undefined) { + if (initialDefinition.positionSize.formula !== undefined) { + try { + positionSize = eval(initialDefinition.positionSize.formula.code); + } catch (err) { + initialDefinition.positionSize.formula.error = err.message + } + if (isNaN(positionSize)) { + if (baseAsset === 'BTC') { + positionSize = balanceAssetA; + } else { + positionSize = balanceAssetB; + } + } else { + if (baseAsset === 'BTC') { + if (positionSize > balanceAssetA) { positionSize = balanceAssetA } + } else { + if (positionSize > balanceAssetB) { positionSize = balanceAssetB } + } + } + } + } + } + + if (tradePositionRate !== 0) { + positionRate = tradePositionRate + } else { + if (initialDefinition.positionRate !== undefined) { + if (initialDefinition.positionRate.formula !== undefined) { + try { + positionRate = eval(initialDefinition.positionRate.formula.code); + } catch (err) { + initialDefinition.positionRate.formula.error = err.message + } + if (isNaN(positionRate)) { + if (baseAsset === 'BTC') { + positionRate = candle.close; + } else { + positionRate = candle.close; + } + } + } + } + } + if (initialDefinition.stopLoss !== undefined) { for (let p = 0; p < initialDefinition.stopLoss.phases.length; p++) { @@ -500,7 +583,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { formulaValue = MAX_STOP_LOSS_VALUE } } catch (err) { - formulaError = err.message + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } } if (isNaN(formulaValue)) { formulaValue = 0; } if (formulaValue < MIN_STOP_LOSS_VALUE) { @@ -553,7 +642,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { formulaValue = MAX_TAKE_PROFIT_VALUE } } catch (err) { - formulaError = err.message + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } } if (isNaN(formulaValue)) { formulaValue = 0; } if (formulaValue < MIN_TAKE_PROFIT_VALUE) { @@ -588,6 +683,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } } + + strategy.positionSize = positionSize + strategy.positionRate = positionRate } let manageStage = strategy.manageStage @@ -612,7 +710,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { formulaValue = MAX_STOP_LOSS_VALUE } } catch (err) { - formulaError = err.message + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } } if (isNaN(formulaValue)) { formulaValue = 0; } if (formulaValue < MIN_STOP_LOSS_VALUE) { @@ -665,7 +769,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { formulaValue = MAX_TAKE_PROFIT_VALUE } } catch (err) { - formulaError = err.message + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } } if (isNaN(formulaValue)) { formulaValue = 0; } if (formulaValue < MIN_TAKE_PROFIT_VALUE) { @@ -700,39 +810,45 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } } - } - function newCondition(key, node) { + function newCondition(key, node) { - let condition; - let error = '' - let value + let condition; + let error = '' + let value - try { - value = eval(node.code); - } catch (err) { - /* - One possible error is that the conditions references a .previous that is undefined. For this - reason and others, we will simply set the value to false. - */ - value = false - node.error = err.message - } + try { + value = eval(node.code); + } catch (err) { + /* + One possible error is that the conditions references a .previous that is undefined. For this + reason and others, we will simply set the value to false. + */ + value = false - condition = { - key: key, - value: value - }; + if (node.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + node.error = err.message + } + } - conditions.set(condition.key, condition); + condition = { + key: key, + value: value + }; - if (condition.value) { - conditionsArrayValues.push(1); - } else { - conditionsArrayValues.push(0); + conditions.set(condition.key, condition); + + if (condition.value) { + conditionsArrayValues.push(1); + } else { + conditionsArrayValues.push(0); + } } } - } /* Trigger On Conditions */ @@ -809,11 +925,12 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } } else { + let stopRunningDate = new Date(candle.begin) if (balance < minimumBalance) { - tradingSystem.error = "Balance below the minimum." + tradingSystem.error = "Min Balance @ " + stopRunningDate.toUTCString() } if (balance > maximumBalance) { - tradingSystem.error = "Balance above the maximum." + tradingSystem.error = "Max Balance @ " + stopRunningDate.toUTCString() } } } @@ -893,7 +1010,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (passed) { - type = '"Sell"'; + type = '"Take Position"'; strategyStage = 'Open Stage'; stopLossStage = 'Open Stage'; @@ -1153,7 +1270,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 +1306,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'; @@ -1211,44 +1328,24 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { ) { takePositionNow = false - /* positionSize default is the whole balance if no size was defined by the user */ + /* tradePositionSize default is the whole balance if no size was defined by the user */ if (baseAsset === 'BTC') { - positionSize = balanceAssetA; + tradePositionSize = balanceAssetA; } else { - positionSize = balanceAssetB; + tradePositionSize = balanceAssetB; } + tradePositionRate = candle.close - /* Check if the user defined a position size */ + /* Check if the user defined a position size or rate */ let strategy = tradingSystem.strategies[currentStrategyIndex]; - let triggerStage = strategy.triggerStage - if (triggerStage !== undefined) { - if (triggerStage.positionSize !== undefined) { - if (triggerStage.positionSize.formula !== undefined) { - try { - positionSize = eval(triggerStage.positionSize.formula.code); - } catch (err) { - triggerStage.positionSize.formula.error = err.message - } - if (isNaN(positionSize)) { - if (baseAsset === 'BTC') { - positionSize = balanceAssetA; - } else { - positionSize = balanceAssetB; - } - } else { - if (baseAsset === 'BTC') { - if (positionSize > balanceAssetA) { positionSize = balanceAssetA} - } else { - if (positionSize > balanceAssetB) { positionSize = balanceAssetB} - } - } - } - } - } + tradePositionSize = strategy.positionSize; + tradePositionRate = strategy.positionRate; + + calculateTakeProfit(); + calculateStopLoss(); marketRate = candle.close; - positionRate = candle.close; previousBalanceAssetA = balanceAssetA; previousBalanceAssetB = balanceAssetB; @@ -1257,11 +1354,11 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { lastTradeROI = 0; if (baseAsset === 'BTC') { - balanceAssetB = balanceAssetB + positionSize * positionRate; - balanceAssetA = balanceAssetA - positionSize; + balanceAssetB = balanceAssetB + tradePositionSize * tradePositionRate; + balanceAssetA = balanceAssetA - tradePositionSize; } else { - balanceAssetA = balanceAssetA + positionSize / positionRate; - balanceAssetB = balanceAssetB - positionSize; + balanceAssetA = balanceAssetA + tradePositionSize / tradePositionRate; + balanceAssetB = balanceAssetB - tradePositionSize; } positionInstant = candle.end; @@ -1293,12 +1390,12 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (baseAsset === 'BTC') { lastTradeProfitLoss = balanceAssetA - previousBalanceAssetA; - lastTradeROI = lastTradeProfitLoss * 100 / positionSize; + lastTradeROI = lastTradeProfitLoss * 100 / tradePositionSize; if (isNaN(lastTradeROI)) { lastTradeROI = 0; } profit = balanceAssetA - initialBalanceA; } else { lastTradeProfitLoss = balanceAssetB - previousBalanceAssetB; - lastTradeROI = lastTradeProfitLoss * 100 / positionSize; + lastTradeROI = lastTradeProfitLoss * 100 / tradePositionSize; if (isNaN(lastTradeROI)) { lastTradeROI = 0; } profit = balanceAssetB - initialBalanceB; } @@ -1356,8 +1453,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategyIndex = -1; stopLoss = 0; - positionRate = 0; - positionSize = 0; + tradePositionRate = 0; + tradePositionSize = 0; positionInstant = undefined; takeProfit = 0; strategyStage = 'No Stage'; @@ -1380,21 +1477,33 @@ 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.OrderClose; + } else { + messageType = MESSAGE_TYPE.OrderUpdate; + } } - orderRecord = createMessage( + let exitOutcome = "" + if (messageType === MESSAGE_TYPE.OrderClose && type === '"Close@TakeProfit"') { + exitOutcome = "TP" + } + if (messageType === MESSAGE_TYPE.OrderClose && type === '"Close@StopLoss"') { + exitOutcome = "SL" + } + + executionMessage = createMessage( messageId, MESSAGE_ENTITY.SimulationEngine, MESSAGE_ENTITY.SimulationExecutor, @@ -1408,19 +1517,19 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { "BTC_USDT", 0, ORDER_TYPE.Limit, - marketRate, + tradePositionRate, stopLoss, takeProfit, ORDER_DIRECTION.Sell, -1, ORDER_STATUS.Signaled, 0, - "") + exitOutcome) } else { - orderRecord = createMessage( + executionMessage = createMessage( messageId, MESSAGE_ENTITY.SimulationEngine, MESSAGE_ENTITY.SimulationExecutor, @@ -1444,6 +1553,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': { @@ -1497,15 +1614,15 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { periods: periods, days: days, anualizedRateOfReturn: anualizedRateOfReturn, - positionRate: positionRate, + positionRate: tradePositionRate, lastTradeROI: lastTradeROI, strategy: currentStrategyIndex, strategyStageNumber: strategyStageNumber, takeProfit: takeProfit, stopLossPhase: stopLossPhase, takeProfitPhase: takeProfitPhase, - orderRecord: orderRecord, - positionSize: positionSize, + executionRecord: executionMessage, + positionSize: tradePositionSize, initialBalanceA: initialBalanceA, minimumBalanceA: minimumBalanceA, maximumBalanceA: maximumBalanceA, @@ -1605,7 +1722,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) { @@ -1620,11 +1737,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } - element = { - direction: 'unknown', - slope: 'unknown' - }; - return element; + return } } catch (err) { @@ -1653,17 +1766,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 +1813,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 +1852,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'; } } @@ -1772,11 +1885,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { begin: dataFile[i][0], end: dataFile[i][1], direction: dataFile[i][2], - period: dataFile[i][3], - firstMovingAverage: dataFile[i][4], - lastMovingAverage: dataFile[i][5], - firstDeviation: dataFile[i][6], - lastDeviation: dataFile[i][7] + period: dataFile[i][3] }; bollingerChannel.previous = previous; @@ -1856,9 +1965,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/src/storage/templates/Simulator/User.Bot.Daily.js b/src/storage/templates/Simulator/User.Bot.Daily.js index 8cc5e30d0..ef105c9a6 100644 --- a/src/storage/templates/Simulator/User.Bot.Daily.js +++ b/src/storage/templates/Simulator/User.Bot.Daily.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/src/storage/templates/Simulator/User.Bot.Market.js b/src/storage/templates/Simulator/User.Bot.Market.js index 80afe2836..a4dc38283 100644 --- a/src/storage/templates/Simulator/User.Bot.Market.js +++ b/src/storage/templates/Simulator/User.Bot.Market.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 + "," + diff --git a/src/storage/templates/Simulator/this.bot.config.json b/src/storage/templates/Simulator/this.bot.config.json index d0d8572de..15b52e5e1 100644 --- a/src/storage/templates/Simulator/this.bot.config.json +++ b/src/storage/templates/Simulator/this.bot.config.json @@ -79,7 +79,7 @@ "major": 1, "minor": 0 }, - "product": "Bollinger-Channels", + "product": "Bollinger-Standard-Channels", "dataSetVersion": "dataSet.V1", "dataSet": "Multi-Period-Market" }, @@ -90,7 +90,7 @@ "major": 1, "minor": 0 }, - "product": "Bollinger-Sub-Channels", + "product": "Bollinger-Standard-Sub-Channels", "dataSetVersion": "dataSet.V1", "dataSet": "Multi-Period-Market" }, @@ -166,7 +166,7 @@ }, "product": "LRC-Points", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" }, { "devTeam": "AAMasters", @@ -177,7 +177,7 @@ }, "product": "Percentage-Bandwidth", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" }, { "devTeam": "AAMasters", @@ -188,7 +188,7 @@ }, "product": "Bollinger-Bands", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" }, { "devTeam": "AAMasters", @@ -197,9 +197,9 @@ "major": 1, "minor": 0 }, - "product": "Bollinger-Channels", + "product": "Bollinger-Standard-Channels", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" }, { "devTeam": "AAMasters", @@ -208,9 +208,9 @@ "major": 1, "minor": 0 }, - "product": "Bollinger-Sub-Channels", + "product": "Bollinger-Standard-Sub-Channels", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" }, { "devTeam": "AAMasters", @@ -221,7 +221,7 @@ }, "product": "Candles", "dataSetVersion": "dataSet.V1", - "dataSet": "Multi-Period-Market" + "dataSet": "Multi-Period-Daily" } ] } diff --git a/src/storage/templates/TradingBot/User.Bot.js b/src/storage/templates/TradingBot/User.Bot.js index c8fc78f3a..d1a4d4820 100644 --- a/src/storage/templates/TradingBot/User.Bot.js +++ b/src/storage/templates/TradingBot/User.Bot.js @@ -42,13 +42,10 @@ exports.newUserBot = function newUserBot(bot, logger) { throw new Error("Execution Parameter Data Set not defined.") } - let key = bot.devTeam + '-simulator-' + bot.codeName + '-Trading-Simulation-' + bot.dataSet + '-dataSet.V1' + let key = bot.devTeam + '-simulator-' + bot.codeName + '-Trading-Execution-' + bot.dataSet + '-dataSet.V1' fileStorage = assistant.dataDependencies.dataSets.get(key) if (fileStorage !== undefined) { - assistant.rememberThis('lastSimulatorEngineMessageId', 0) - assistant.rememberThis('lastStopLoss', 0) - assistant.rememberThis('lastTakeProfit', 0) callBackFunction(global.DEFAULT_OK_RESPONSE) } else { logError('initialize -> Failed to initialize storage. Key not found:' + key) @@ -93,21 +90,72 @@ exports.newUserBot = function newUserBot(bot, logger) { }) } + function getValueFromPreviousExecution(key) { + let value = assistant.remindMeOf(key) + if (value === undefined) + value = 0 + return value + } + async function executorLogic() { try { let indicatorFileContent = await getIndicatorFile() let simulatorEngineMessage = getSimulatorEngineMessageFromFile(indicatorFileContent) let autopilotResponse = await getAutopilot() - let stopLoss, takeProfit + let stopLoss, takeProfit, receivedMessageId if (simulatorEngineMessage === undefined) { logWarn('start -> Simulator message not available. Will proceed to check SL and TP from previous execution.') - stopLoss = assistant.remindMeOf('lastStopLoss') - takeProfit = assistant.remindMeOf('lastTakeProfit') + stopLoss = getValueFromPreviousExecution('lastStopLoss') + takeProfit = getValueFromPreviousExecution('lastTakeProfit') + receivedMessageId = 0 } else { logInfo('Processing simulator record: ' + JSON.stringify(simulatorEngineMessage)) - stopLoss = simulatorEngineMessage.order.stop - takeProfit = simulatorEngineMessage.order.takeProfit + receivedMessageId = simulatorEngineMessage.id + + // Verify if there is an inconsistent state between the simulator and executor + let isATradeOpen = (getValueFromPreviousExecution('lastSimulatorEngineMessageId') > 0) + let isMessageAHeartBeat = (simulatorEngineMessage.messageType === MESSAGE_TYPE.HeartBeat) + if (isATradeOpen && isMessageAHeartBeat) { + logWarn('An inconsisten state was detected: there is an open trade and a close trade was expected.') + let skippedMessageOrderClose = getSkippedMessageOrderClose(indicatorFileContent) + if (skippedMessageOrderClose === undefined) { + logWarn('There was not a Skipped Message Order Close. Closing the position the best possible.') + stopLoss = assistant.getMarketRate() + takeProfit = assistant.getMarketRate() + } else { + let lastSimulatorEngineMessageId = getValueFromPreviousExecution('lastSimulatorEngineMessageId') + if (skippedMessageOrderClose.id > lastSimulatorEngineMessageId) { + logWarn('The Skipped Message Order Close was found and using it to set the SL and TP.') + isMessageAnOrderClose = (simulatorEngineMessage.messageType === MESSAGE_TYPE.OrderClose) + isStopLoss = (simulatorEngineMessage.order.exitOutcome === ORDER_EXIT_OUTCOME.StopLoss) + isTakeProfit = (simulatorEngineMessage.order.exitOutcome === ORDER_EXIT_OUTCOME.StopLoss) + } else { + logWarn('One Message Order Close was found but is older than the Open Order. Closing the position the best possible.') + stopLoss = assistant.getMarketRate() + takeProfit = assistant.getMarketRate() + } + } + } + + // Validations to check the sync state between the simulator and executor + let isMessageAnOrderUpdate = (simulatorEngineMessage.messageType === MESSAGE_TYPE.OrderUpdate) + let isMessageAnOrderClose = (simulatorEngineMessage.messageType === MESSAGE_TYPE.OrderClose) + let isStopLoss = (simulatorEngineMessage.order.exitOutcome === ORDER_EXIT_OUTCOME.StopLoss) + let isTakeProfit = (simulatorEngineMessage.order.exitOutcome === ORDER_EXIT_OUTCOME.StopLoss) + + if (isMessageAnOrderUpdate) { + stopLoss = simulatorEngineMessage.order.stop + takeProfit = simulatorEngineMessage.order.takeProfit + } else if (isMessageAnOrderClose && isStopLoss) { + stopLoss = assistant.getMarketRate() + takeProfit = 0 + } else if (isMessageAnOrderClose && isTakeProfit) { + stopLoss = 0 + takeProfit = assistant.getMarketRate() + } + assistant.rememberThis('lastStopLoss', stopLoss) + assistant.rememberThis('lastTakeProfit', takeProfit) } // Checking Stop Loss @@ -120,7 +168,7 @@ exports.newUserBot = function newUserBot(bot, logger) { let position = await createBuyPosition(currentRate) let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = position.id + simulatorExecutorMessage.id = receivedMessageId simulatorExecutorMessage.order.id = position.id simulatorExecutorMessage.order.rate = currentRate simulatorExecutorMessage.order.stop = stopLoss @@ -137,6 +185,7 @@ exports.newUserBot = function newUserBot(bot, logger) { assistant.rememberThis('lastTakeProfit', 0) } catch (error) { let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() + simulatorExecutorMessage.id = receivedMessageId simulatorExecutorMessage.from = MESSAGE_ENTITY.TradingAssistant simulatorExecutorMessage.to = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.order.rate = position.rate @@ -160,7 +209,7 @@ exports.newUserBot = function newUserBot(bot, logger) { let position = await createBuyPosition(currentRate, assetABalance) let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = position.id + simulatorExecutorMessage.id = receivedMessageId simulatorExecutorMessage.order.id = position.id simulatorExecutorMessage.order.rate = currentRate simulatorExecutorMessage.order.stop = stopLoss @@ -177,6 +226,7 @@ exports.newUserBot = function newUserBot(bot, logger) { assistant.rememberThis('lastTakeProfit', 0) } catch (error) { let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() + simulatorExecutorMessage.id = receivedMessageId simulatorExecutorMessage.from = MESSAGE_ENTITY.TradingAssistant simulatorExecutorMessage.to = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.order.rate = currentRate @@ -185,6 +235,7 @@ exports.newUserBot = function newUserBot(bot, logger) { simulatorExecutorMessage.order.direction = ORDER_DIRECTION.Buy simulatorExecutorMessage.order.size = assetABalance simulatorExecutorMessage.order.status = ORDER_STATUS.Rejected + simulatorExecutorMessage.order.statusDetails = error.message let message = createMessageFromObject(simulatorExecutorMessage) assistant.addExtraData(message) @@ -214,7 +265,7 @@ exports.newUserBot = function newUserBot(bot, logger) { if (simulatorEngineMessage.messageType === MESSAGE_TYPE.Order && simulatorEngineMessage.order.direction === ORDER_DIRECTION.Sell) { - let lastSimulatorEngineMessageId = assistant.remindMeOf('lastSimulatorEngineMessageId') + let lastSimulatorEngineMessageId = getValueFromPreviousExecution('lastSimulatorEngineMessageId') if (lastSimulatorEngineMessageId >= simulatorEngineMessage.id) { logInfo("manageCloneInAutopilotOn -> Order message was previously processed.") return @@ -223,7 +274,7 @@ exports.newUserBot = function newUserBot(bot, logger) { try { let position = await createSellPosition(currentRate, assetBBalance) let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = position.id + simulatorExecutorMessage.id = simulatorEngineMessage.id simulatorExecutorMessage.order.id = position.id simulatorExecutorMessage.order.rate = currentRate simulatorExecutorMessage.order.stop = simulatorEngineMessage.order.stop @@ -233,11 +284,12 @@ exports.newUserBot = function newUserBot(bot, logger) { let message = createMessageFromObject(simulatorExecutorMessage) assistant.addExtraData(message) - assistant.rememberThis('lastSimulatorEngineMessageId', parseInt(simulatorEngineMessage.id)) + assistant.rememberThis('lastSimulatorEngineMessageId', simulatorEngineMessage.id) assistant.rememberThis('lastStopLoss', simulatorEngineMessage.order.stop) assistant.rememberThis('lastTakeProfit', simulatorEngineMessage.order.takeProfit) } catch (error) { let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() + simulatorExecutorMessage.id = receivedMessageId simulatorExecutorMessage.from = MESSAGE_ENTITY.TradingAssistant simulatorExecutorMessage.to = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.messageType = MESSAGE_TYPE.Order @@ -247,6 +299,7 @@ exports.newUserBot = function newUserBot(bot, logger) { simulatorExecutorMessage.order.direction = ORDER_DIRECTION.Sell simulatorExecutorMessage.order.size = assetBBalance simulatorExecutorMessage.order.status = ORDER_STATUS.Rejected + simulatorExecutorMessage.order.statusDetails = error.message let message = createMessageFromObject(simulatorExecutorMessage) assistant.addExtraData(message) @@ -272,7 +325,7 @@ exports.newUserBot = function newUserBot(bot, logger) { // 1) Save audit containing what we received from the cockpit let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = 0 + simulatorExecutorMessage.id = simulatorEngineMessage.id simulatorExecutorMessage.from = MESSAGE_ENTITY.TradingCokpit simulatorExecutorMessage.to = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.order = acceptedSignal.orderData // we save the order as received @@ -285,7 +338,7 @@ exports.newUserBot = function newUserBot(bot, logger) { // 3) Save the audit of the order placed simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = position.id + simulatorExecutorMessage.id = simulatorEngineMessage.id simulatorExecutorMessage.from = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.to = MESSAGE_ENTITY.TradingAssistant simulatorExecutorMessage.dateTime = position.date @@ -307,12 +360,13 @@ exports.newUserBot = function newUserBot(bot, logger) { } catch (error) { // Update the cockpit with the error let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = 0 + simulatorExecutorMessage.id = simulatorEngineMessage.id simulatorExecutorMessage.from = MESSAGE_ENTITY.SimulationExecutor simulatorExecutorMessage.to = MESSAGE_ENTITY.TradingCokpit simulatorExecutorMessage.messageType = MESSAGE_TYPE.Order simulatorExecutorMessage.dateTime = bot.processDatetime.valueOf() simulatorExecutorMessage.order.status = ORDER_STATUS.Rejected + simulatorExecutorMessage.order.statusDetails = error.message simulatorExecutorMessage.order = acceptedSignal.order @@ -405,7 +459,7 @@ exports.newUserBot = function newUserBot(bot, logger) { // 2) Save the audit message for the received info from Trading Simulator let simulatorExecutorMessage = buildBasicSimulatorExecutorMessage() - simulatorExecutorMessage.id = 0 + simulatorExecutorMessage.id = simulatorEngineMessage.id simulatorExecutorMessage.to = MESSAGE_ENTITY.TradingCokpit simulatorExecutorMessage.messageType = MESSAGE_TYPE.Order simulatorExecutorMessage.order.id = 0 @@ -524,17 +578,17 @@ exports.newUserBot = function newUserBot(bot, logger) { // Storage functions async function getIndicatorFile() { - logInfo('getIndicatorFile -> Entering function.') + logInfo('getIndicatorFile -> Entering function. ' + bot.processDatetime.toISOString()) let filePath if (bot.processes[0].timePeriod > 2700000) { // Market Files - filePath = 'Trading-Simulation/' + bot.dataSet + '/' + bot.timePeriodFileStorage + filePath = 'Trading-Execution/' + bot.dataSet + '/' + bot.timePeriodFileStorage } else { // Daily Files let dateTime = bot.processDatetime let datePath = dateTime.getUTCFullYear() + '/' + pad(dateTime.getUTCMonth() + 1, 2) + '/' + pad(dateTime.getUTCDate(), 2) - filePath = 'Trading-Simulation/' + bot.dataSet + '/' + bot.timePeriodFileStorage + '/' + datePath + filePath = 'Trading-Execution/' + bot.dataSet + '/' + bot.timePeriodFileStorage + '/' + datePath } /* @@ -561,7 +615,7 @@ exports.newUserBot = function newUserBot(bot, logger) { if (bot.processDatetime.valueOf() <= lastAvailableDateTime || !isExecutionToday()) { for (let i = 0; i < indicatorFileContent.length; i++) { if (bot.processDatetime.valueOf() >= indicatorFileContent[i][0] && bot.processDatetime.valueOf() < indicatorFileContent[i][1]) { - return getMessage(indicatorFileContent[i][25]) + return getMessage(indicatorFileContent[i][2]) } } @@ -570,7 +624,7 @@ exports.newUserBot = function newUserBot(bot, logger) { // Running live we will process last available Indicator Message only if it's delayed 10 minutes top let maxTolerance = 10 * 60 * 1000 if (bot.processDatetime.valueOf() <= (lastAvailableDateTime + maxTolerance)) { - return getMessage(indicatorFileContent[lastIndexIndicatorFile][25]) + return getMessage(indicatorFileContent[lastIndexIndicatorFile][2]) } else { logWarn('getSimulatorEngineMessageFromFile -> Last available indicator older than 10 minutes.') } @@ -581,6 +635,22 @@ exports.newUserBot = function newUserBot(bot, logger) { } } + function getSkippedMessageOrderClose(indicatorFileContent) { + try { + let lastIndexIndicatorFile = indicatorFileContent.length - 1 + + for (let i = lastIndexIndicatorFile; i >= 0; i--) { + let simulatorMessage = getMessage(indicatorFileContent[i][2]) + if (simulatorMessage.messageType === MESSAGE_TYPE.OrderClose) { + return simulatorMessage + } + } + } catch (error) { + logError('getSkippedMessageOrderClose -> error = ' + error.message) + throw global.DEFAULT_RETRY_RESPONSE + } + } + // Helper Functions function isExecutionToday() { let localDate = new Date() @@ -774,16 +844,18 @@ exports.newUserBot = function newUserBot(bot, logger) { simulatorExecutorMessage.dateTime = bot.processDatetime.valueOf() simulatorExecutorMessage.order = {} + simulatorExecutorMessage.order.id = 0 simulatorExecutorMessage.order.dateTime = bot.processDatetime.valueOf() simulatorExecutorMessage.order.creator = ORDER_CREATOR.SimulationEngine simulatorExecutorMessage.order.owner = ORDER_OWNER.User simulatorExecutorMessage.order.exchange = global.EXCHANGE_NAME - simulatorExecutorMessage.order.market = global.MARKET.name + simulatorExecutorMessage.order.market = global.MARKET.assetA + '_' + global.MARKET.assetB simulatorExecutorMessage.order.marginEnabled = ORDER_MARGIN_ENABLED.False simulatorExecutorMessage.order.type = ORDER_TYPE.Limit simulatorExecutorMessage.order.status = ORDER_STATUS.Placed simulatorExecutorMessage.order.sizeFilled = 0 simulatorExecutorMessage.order.exitOutcome = '' + simulatorExecutorMessage.order.statusMessage = '' return simulatorExecutorMessage } diff --git a/src/storage/templates/TradingBot/this.bot.config.json b/src/storage/templates/TradingBot/this.bot.config.json index c3d22f52e..d59dba4bc 100644 --- a/src/storage/templates/TradingBot/this.bot.config.json +++ b/src/storage/templates/TradingBot/this.bot.config.json @@ -7,7 +7,7 @@ "minor": 0, "patch": 0 }, - "devTeam": "aavikings", + "devTeam": "vikings", "profilePicture": "bumblebee.png", "dataSetVersion": "dataSet.V1", "processes": [ @@ -73,7 +73,7 @@ "major": 1, "minor": 0 }, - "product": "Trading-Simulation", + "product": "Trading-Execution", "dataSetVersion": "dataSet.V1", "dataSet": "Multi-Period-Market" }, @@ -84,7 +84,7 @@ "major": 1, "minor": 0 }, - "product": "Trading-Simulation", + "product": "Trading-Execution", "dataSetVersion": "dataSet.V1", "dataSet": "Multi-Period-Daily" } @@ -101,27 +101,7 @@ { "codeName": "Oficial History", "type": "File Sequence", - "validPeriods": [ - "24-hs", - "12-hs", - "08-hs", - "06-hs", - "04-hs", - "03-hs", - "02-hs", - "01-hs", - "45-min", - "40-min", - "30-min", - "20-min", - "15-min", - "10-min", - "05-min", - "04-min", - "03-min", - "02-min", - "01-min" - ], + "validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs", "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ], "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", "fileName": "Execution.History.Live.@Sequence.json" } @@ -131,11 +111,11 @@ "name": "Poloniex" } ], - "plotter": { - "devTeam": "AAMasters", - "codeName": "PlottersTradingSimulation", - "moduleName": "SimulationExecution" - } + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } }, { "codeName": "Backtest Trading History", @@ -146,27 +126,7 @@ { "codeName": "Backtest History", "type": "File Sequence", - "validPeriods": [ - "24-hs", - "12-hs", - "08-hs", - "06-hs", - "04-hs", - "03-hs", - "02-hs", - "01-hs", - "45-min", - "40-min", - "30-min", - "20-min", - "15-min", - "10-min", - "05-min", - "04-min", - "03-min", - "02-min", - "01-min" - ], + "validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs", "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ], "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", "fileName": "Execution.History.Backtest.@Sequence.json" } @@ -176,11 +136,11 @@ "name": "Poloniex" } ], - "plotter": { - "devTeam": "AAMasters", - "codeName": "PlottersTradingSimulation", - "moduleName": "SimulationExecution" - } + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } }, { "codeName": "Competition Trading History", @@ -191,27 +151,7 @@ { "codeName": "Competition History", "type": "File Sequence", - "validPeriods": [ - "24-hs", - "12-hs", - "08-hs", - "06-hs", - "04-hs", - "03-hs", - "02-hs", - "01-hs", - "45-min", - "40-min", - "30-min", - "20-min", - "15-min", - "10-min", - "05-min", - "04-min", - "03-min", - "02-min", - "01-min" - ], + "validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs", "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ], "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", "fileName": "Execution.History.Competition.@Sequence.json" } @@ -221,11 +161,11 @@ "name": "Poloniex" } ], - "plotter": { - "devTeam": "AAMasters", - "codeName": "PlottersTradingSimulation", - "moduleName": "SimulationExecution" - } + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } } ], "marketRateProvider": {