From 5f6900ef3fe1c014b5596fd1a16d882908cb31d4 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Thu, 15 Aug 2019 19:27:13 +0200 Subject: [PATCH 1/3] Improvements on Live Trading --- Commons.js | 90 +++++++++++++++++++-------------- Run.js | 2 +- TradingEngineProcessMainLoop.js | 8 +-- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/Commons.js b/Commons.js index b49271578..42e713d8a 100644 --- a/Commons.js +++ b/Commons.js @@ -368,7 +368,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* If any of the needed indicators is missing, then that period is not calculated */ - if (candle.begin < initialDate.valueOf()) { + if (candle.end < initialDate.valueOf()) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record before the initialDate."); } controlLoop(); return @@ -405,16 +405,16 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } /* 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)) { + //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. */ - controlLoop(); - return + // controlLoop(); + // return /* 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) { controlLoop(); @@ -955,6 +955,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategy.begin = candle.begin; currentStrategy.beginRate = candle.min; currentStrategy.endRate = candle.min; // In case the strategy does not get exited + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to Trigger Stage because conditions at Trigger On Event were met."); } break; } } @@ -1009,6 +1011,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategy.status = 1; strategyStage = 'No Stage'; currentStrategyIndex = -1; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to No Stage because conditions at the Trigger Off Event were met."); } break; } } @@ -1057,6 +1061,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentTrade.begin = candle.begin; currentTrade.beginRate = candle.close; takePositionNow = true + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Conditions at the Take Position Event were met."); } break; } } @@ -1377,7 +1383,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { takePositionNow === true ) { takePositionNow = false - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Entering code block."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Entering code block."); } /* Position size and rate */ let strategy = tradingSystem.strategies[currentStrategyIndex]; @@ -1408,11 +1414,11 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { break } case "Taking Position": { // Waiting for a confirmation that the position was taken. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Exiting code block because status is Taking Position."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is Taking Position."); } break } case "In a Position": { // This should mean that we already put the order at the exchange. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Exiting code block because status is In a Position."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is In a Position."); } break } } @@ -1430,12 +1436,12 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { function putOpeningOrder() { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Entering function."); } /* We wont take a position unless we are withing the startDate and the endDate range */ if (startDate !== undefined) { - if (candle.begin < startDate.valueOf()) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because current candle begins before the start date. -> startDate = " + startDate); } + if (candle.end < startDate.valueOf()) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because current candle ends before the start date. -> startDate = " + startDate); } takePositionAtSimulation() return; } @@ -1456,7 +1462,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (positions.length > 0) { let position = positions[positions.length - 1] // We are allways checking the the last position is not open. if (position.status === 'open') { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because the last position is still open. "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because the last position is still open. "); } afterLoop(); return } @@ -1467,7 +1473,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (interExecutionMemory.executionContext !== undefined) { if (interExecutionMemory.executionContext.periods !== undefined) { if (periods <= interExecutionMemory.executionContext.periods) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution." ); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution." ); } takePositionAtSimulation() return; } @@ -1478,7 +1484,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let today = new Date(Math.trunc((new Date().valueOf()) / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS) let processDay = new Date(Math.trunc(currentDay.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS) if (today.valueOf() !== processDay.valueOf()) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because the current candle belongs to the previous day and that is considered simulation and not live trading."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because the current candle belongs to the previous day and that is considered simulation and not live trading."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> today = " + today); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> processDay = " + processDay); } takePositionAtSimulation() return; } @@ -1508,16 +1516,16 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { status: "Taking Position" } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Ready to put order."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Ready to put order."); } assistant.putPosition(positionDirection, openPositionRate, amountA, amountB, onOrderPut) function onOrderPut(err) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Entering function."); } try { switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } interExecutionMemory.executionContext = { status: "In a Position", periods: periods, @@ -1528,24 +1536,26 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { return; } case global.DEFAULT_FAIL_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Message = " + err.message); } strategy.openStage.openExecution.error = err.message afterLoop() return; } case global.DEFAULT_RETRY_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Message = " + err.message); } strategy.openStage.openExecution.error = err.message afterLoop() return; } } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> putOpeningOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } catch (err) { - logger.write(MODULE_NAME, "[ERROR] runSimulation -> putOpeningOrder -> onOrderPut -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } @@ -1589,6 +1599,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } addRecord(); + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionAtSimulation -> Exiting Loop Body after taking position at simulation."); } controlLoop(); return } @@ -1597,7 +1608,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* Closing a Position */ if (strategyStage === 'Close Stage') { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Entering code block."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Entering code block."); } /* Position size and rate */ let strategy = tradingSystem.strategies[currentStrategyIndex]; @@ -1607,7 +1618,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (interExecutionMemory.executionContext !== undefined) { switch (interExecutionMemory.executionContext.status) { case "Without a Position": { // No way to close anything at the exchange. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Exiting code block because status is Without a Position."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Without a Position."); } break } case "In a Position": { // This should mean that we already put the order at the exchange. @@ -1630,7 +1641,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } case "Position Closed": { // - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Exiting code block because status is Position Closed."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Position Closed."); } break } } @@ -1648,7 +1659,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (positions.length > 0) { let position = positions[positions.length - 1] // We are allways checking the the last position is not open. if (position.status === 'open') { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Exiting function because status of last position is Open."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> Exiting function because status of last position is Open."); } afterLoop(); return } @@ -1659,7 +1670,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (interExecutionMemory.executionContext !== undefined) { if (interExecutionMemory.executionContext.periods !== undefined) { if (periods <= interExecutionMemory.executionContext.periods) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Exiting function because this closing was already submited at a previous execution."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> Exiting function because this closing was already submited at a previous execution."); } closePositionAtSimulation() return; } @@ -1691,16 +1702,16 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { status: "Closing Position" } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> About to close position at the exchange."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> About to close position at the exchange."); } assistant.putPosition(positionDirection, closePositionRate, amountA, amountB, onOrderPut) function onOrderPut(err) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> Entering function."); } try { switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } interExecutionMemory.executionContext = { status: "Position Closed", periods: periods, @@ -1711,25 +1722,25 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { return; } case global.DEFAULT_FAIL_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putClosingOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } /* We will assume that the problem is temporary, and expect that it will work at the next execution.*/ strategy.closeStage.closeExecution.error = err.message afterLoop() return; } case global.DEFAULT_RETRY_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } strategy.closeStage.closeExecution.error = err.message afterLoop() return; } } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> putClosingOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } catch (err) { - logger.write(MODULE_NAME, "[ERROR] runSimulation -> putClosingOrder -> onOrderPut -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] runSimulation -> loop -> putClosingOrder -> onOrderPut -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } @@ -1820,6 +1831,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { takeProfitStage = 'No Stage'; stopLossPhase = 0; takeProfitPhase = 0; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> closePositionAtSimulation -> Exiting Loop Body after closing position at simulation."); } controlLoop(); return } @@ -1829,6 +1842,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { marketRate = candle.close; addRecord(); + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Exiting Loop Body after adding a record."); } controlLoop(); return @@ -1850,13 +1864,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { messageType = MESSAGE_TYPE.Order; orderId++; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> addRecord -> Taking Position Now. "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> addRecord -> Taking Position Now. "); } } else { if (type === '"Close@TakeProfit"' || type === '"Close@StopLoss"') { messageType = MESSAGE_TYPE.OrderClose; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> addRecord -> Closing Position Now. "); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> addRecord -> Closing Position Now. "); } } else { messageType = MESSAGE_TYPE.OrderUpdate; diff --git a/Run.js b/Run.js index 1fa389940..8ecd0b5cf 100644 --- a/Run.js +++ b/Run.js @@ -241,7 +241,7 @@ async function readExecutionConfiguration(execution) { let live = { run: 'false', resumeExecution: execution.resumeExecution, - beginDatetime: initialDatetime, + beginDatetime: new Date(definition.simulationParams.timestamp).toISOString(), endDatetime: finalDatetime } diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index bcfdd1727..b6dbc7661 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -54,8 +54,8 @@ } USER_BOT_MODULE = {} - //USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - USER_BOT_MODULE.newUserBot = eval(text); // Use this for production + USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + //USER_BOT_MODULE.newUserBot = eval(text); // Use this for production filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; filePath += "/Commons.js" @@ -70,8 +70,8 @@ return; } COMMONS_MODULE = {} - //COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - COMMONS_MODULE.newCommons = eval(text); // Use this for production + COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + //COMMONS_MODULE.newCommons = eval(text); // Use this for production callBackFunction(global.DEFAULT_OK_RESPONSE); } From 2ebae6f1fb68b5fd57ffe1f18090c0612aa83ee9 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 16 Aug 2019 17:49:51 +0200 Subject: [PATCH 2/3] BUG Fixed initial Date on Backtest --- Commons.js | 118 +++++++++++++++++++++++++++-------------------------- Root.js | 24 ++++++++--- 2 files changed, 79 insertions(+), 63 deletions(-) diff --git a/Commons.js b/Commons.js index 42e713d8a..536197b36 100644 --- a/Commons.js +++ b/Commons.js @@ -1391,42 +1391,44 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { tradePositionSize = strategy.positionSize; tradePositionRate = strategy.positionRate; - /* We see if we need to put the actual order at the exchange. */ - - if (interExecutionMemory.executionContext !== undefined) { - switch (interExecutionMemory.executionContext.status) { - case "Without a Position": { // We need to put the order because It was not put yet. - if (strategy.openStage !== undefined) { - if (strategy.openStage.openExecution !== undefined) { - putOpeningOrder() - return + /* Check that we are in LIVE MODE */ + if (process.env.START_MODE === "live") { + /* We see if we need to put the actual order at the exchange. */ + if (interExecutionMemory.executionContext !== undefined) { + switch (interExecutionMemory.executionContext.status) { + case "Without a Position": { // We need to put the order because It was not put yet. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } } + break } - break - } - case "Position Closed": { // Waiting for a confirmation that the position was closed. - if (strategy.openStage !== undefined) { - if (strategy.openStage.openExecution !== undefined) { - putOpeningOrder() - return + case "Position Closed": { // Waiting for a confirmation that the position was closed. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } } + break + } + case "Taking Position": { // Waiting for a confirmation that the position was taken. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is Taking Position."); } + break + } + case "In a Position": { // This should mean that we already put the order at the exchange. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is In a Position."); } + break } - break } - case "Taking Position": { // Waiting for a confirmation that the position was taken. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is Taking Position."); } - break - } - case "In a Position": { // This should mean that we already put the order at the exchange. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionNow -> Exiting code block because status is In a Position."); } - break - } - } - } else { // The context does not exist so it means we are not in a position. - if (strategy.openStage !== undefined) { - if (strategy.openStage.openExecution !== undefined) { - putOpeningOrder() - return + } else { // The context does not exist so it means we are not in a position. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } } } } @@ -1613,36 +1615,38 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* Position size and rate */ let strategy = tradingSystem.strategies[currentStrategyIndex]; - /* We see if we need to put the actual order at the exchange. */ - - if (interExecutionMemory.executionContext !== undefined) { - switch (interExecutionMemory.executionContext.status) { - case "Without a Position": { // No way to close anything at the exchange. - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Without a Position."); } - break - } - case "In a Position": { // This should mean that we already put the order at the exchange. - if (strategy.closeStage !== undefined) { - if (strategy.closeStage.closeExecution !== undefined) { - putClosingOrder() - return - } + /* Check that we are in LIVE MODE */ + if (process.env.START_MODE === "live") { + /* We see if we need to put the actual order at the exchange. */ + if (interExecutionMemory.executionContext !== undefined) { + switch (interExecutionMemory.executionContext.status) { + case "Without a Position": { // No way to close anything at the exchange. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Without a Position."); } + break } - break - } - case "Closing Position": { // Waiting for a confirmation that the position was taken. - if (strategy.closeStage !== undefined) { - if (strategy.closeStage.closeExecution !== undefined) { - putClosingOrder() - return + case "In a Position": { // This should mean that we already put the order at the exchange. + if (strategy.closeStage !== undefined) { + if (strategy.closeStage.closeExecution !== undefined) { + putClosingOrder() + return + } } + break + } + case "Closing Position": { // Waiting for a confirmation that the position was taken. + if (strategy.closeStage !== undefined) { + if (strategy.closeStage.closeExecution !== undefined) { + putClosingOrder() + return + } + } + break } - break - } - case "Position Closed": { // - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Position Closed."); } - break + case "Position Closed": { // + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Closing a Position -> Exiting code block because status is Position Closed."); } + break + } } } } diff --git a/Root.js b/Root.js index ff3e8c56f..07a9cc04e 100644 --- a/Root.js +++ b/Root.js @@ -238,15 +238,27 @@ if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market") { processConfig.framework.startDate.resumeExecution = false; if (processConfig.startMode.noTime !== undefined) { - if (processConfig.startMode.noTime.beginDatetime !== undefined) { - processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; - processConfig.framework.startDate.resumeExecution = false; + if (processConfig.startMode.noTime.run === "true") { + if (processConfig.startMode.noTime.beginDatetime !== undefined) { + processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; + processConfig.framework.startDate.resumeExecution = false; + } } } if (processConfig.startMode.live !== undefined) { - if (processConfig.startMode.live.beginDatetime !== undefined) { - processConfig.framework.startDate.fixedDate = processConfig.startMode.live.beginDatetime; - processConfig.framework.startDate.resumeExecution = false; + if (processConfig.startMode.live.run === "true") { + if (processConfig.startMode.live.beginDatetime !== undefined) { + processConfig.framework.startDate.fixedDate = processConfig.startMode.live.beginDatetime; + processConfig.framework.startDate.resumeExecution = false; + } + } + } + if (processConfig.startMode.backtest !== undefined) { + if (processConfig.startMode.backtest.run === "true") { + if (processConfig.startMode.backtest.beginDatetime !== undefined) { + processConfig.framework.startDate.fixedDate = processConfig.startMode.backtest.beginDatetime; + processConfig.framework.startDate.resumeExecution = false; + } } } } From 180f1cd74687a8bacb641ef77d289e82ef8ca9ac Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 17 Aug 2019 12:23:33 +0200 Subject: [PATCH 3/3] Reading Bot from Teams source --- Commons.js | 50 +++++++++++++++++++++++++-------- TradingEngineProcessMainLoop.js | 8 +++--- User.Bot.js | 4 ++- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Commons.js b/Commons.js index 536197b36..0c2964ef1 100644 --- a/Commons.js +++ b/Commons.js @@ -194,6 +194,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let hitRatio = 0; let ROI = 0; let days = 0; + let positionDays = 0; let anualizedRateOfReturn = 0; let type = '""'; let marketRate = 0; @@ -256,6 +257,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let fails = 0; let hits = 0; let periods = 0; + let positionPeriods = 0; /* Message to the Simulation Executor */ @@ -275,6 +277,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { yesterday.fails = 0; yesterday.hits = 0; yesterday.Periods = 0; + yesterday.positionPeriods = 0; yesterday.orderId = 0; yesterday.messageId = 0; @@ -298,6 +301,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { interExecutionMemory.fails = 0; interExecutionMemory.hits = 0; interExecutionMemory.periods = 0; + interExecutionMemory.positionPeriods = 0; interExecutionMemory.orderId = 0; interExecutionMemory.messageId = 0; @@ -328,6 +332,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { fails = interExecutionMemory.fails; hits = interExecutionMemory.hits; periods = interExecutionMemory.periods; + positionPeriods = interExecutionMemory.positionPeriods; orderId = interExecutionMemory.orderId; messageId = interExecutionMemory.messageId; @@ -405,16 +410,17 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } /* 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)) { + 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. */ - // controlLoop(); - // return + controlLoop(); + return /* 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) { controlLoop(); @@ -1284,6 +1290,26 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } + /* Keeping Position Counters Up-to-date */ + if ( + (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') + ) { + + if (takePositionNow === true) { + positionPeriods = 0 + yesterday.positionPeriods = 0 + } + + positionPeriods++; + positionDays = positionPeriods * timePeriod / ONE_DAY_IN_MILISECONDS; + + if (currentDay !== undefined) { // This means that we are processing Daily Files + if (candle.end < currentDay.valueOf()) { + yesterday.positionPeriods++; + } + } + } + /* Checking if Stop or Take Profit were hit */ if ( (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') && @@ -1501,14 +1527,14 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (baseAsset === 'BTC') { positionDirection = "sell" - openPositionRate = tradePositionRate - 100 // Provisional stuff to simulate a market order. Put the price lower to get it executed quickly + openPositionRate = tradePositionRate amountA = tradePositionSize * openPositionRate amountB = tradePositionSize } else { positionDirection = "buy" - openPositionRate = tradePositionRate + 100 // Provisional stuff to simulate a market order. Put the price higher to get it executed quickly + openPositionRate = tradePositionRate amountA = tradePositionSize amountB = tradePositionSize / openPositionRate @@ -1568,7 +1594,6 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionAtSimulation -> Entering function."); } /* Continue with the simulation */ - calculateTakeProfit(); calculateStopLoss(); @@ -2017,7 +2042,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { initialBalanceB: initialBalanceB, minimumBalanceB: minimumBalanceB, maximumBalanceB: maximumBalanceB, - baseAsset: quotedBaseAsset + baseAsset: quotedBaseAsset, + positionPeriods: positionPeriods, + positionDays: positionDays } recordsArray.push(simulationRecord); @@ -2111,6 +2138,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { interExecutionMemory.fails = interExecutionMemory.fails + yesterday.fails; interExecutionMemory.hits = interExecutionMemory.hits + yesterday.hits; interExecutionMemory.periods = interExecutionMemory.periods + yesterday.Periods; + interExecutionMemory.positionPeriods = interExecutionMemory.positionPeriods + yesterday.positionPeriods; interExecutionMemory.messageId = interExecutionMemory.messageId + yesterday.messageId; interExecutionMemory.orderId = interExecutionMemory.orderId + yesterday.orderId; diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index b6dbc7661..bcfdd1727 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -54,8 +54,8 @@ } USER_BOT_MODULE = {} - USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - //USER_BOT_MODULE.newUserBot = eval(text); // Use this for production + //USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + USER_BOT_MODULE.newUserBot = eval(text); // Use this for production filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; filePath += "/Commons.js" @@ -70,8 +70,8 @@ return; } COMMONS_MODULE = {} - COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - //COMMONS_MODULE.newCommons = eval(text); // Use this for production + //COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + COMMONS_MODULE.newCommons = eval(text); // Use this for production callBackFunction(global.DEFAULT_OK_RESPONSE); } diff --git a/User.Bot.js b/User.Bot.js index ca0130408..89b84fe38 100644 --- a/User.Bot.js +++ b/User.Bot.js @@ -248,7 +248,9 @@ record.initialBalanceB + "," + record.minimumBalanceB + "," + record.maximumBalanceB + "," + - record.baseAsset + "]"; + record.baseAsset + "," + + record.positionPeriods + "," + + record.positionDays + "]"; if (separator === "") { separator = ","; }