diff --git a/LowFrequencyTrading/TradingOrders.js b/LowFrequencyTrading/TradingOrders.js index d03b913ef..464f25a09 100644 --- a/LowFrequencyTrading/TradingOrders.js +++ b/LowFrequencyTrading/TradingOrders.js @@ -367,8 +367,8 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM actualRateSimulation() percentageFilledSimulation() - sizeFilledSimulation() feesPaidSimulation() + sizeFilledSimulation() doTheAccounting( tradingEngineStage, @@ -430,67 +430,6 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM tradingEngineOrder.orderStatistics.actualRate.value = global.PRECISE(tradingEngineOrder.orderStatistics.actualRate.value, 10) } - function feesPaidSimulation() { - /* Fees Paid Simulation */ - let calculatedBasedOnTradingSystem = false - - /* Based on the Trading System Definition */ - if (tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid !== undefined) { - if (tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage !== undefined) { - if (tradingEngineOrder.orderBaseAsset.feesPaid.value === tradingEngineOrder.orderBaseAsset.feesPaid.config.initialValue) { - - tradingEngineOrder.orderBaseAsset.feesPaid.value = - tradingEngineOrder.orderBaseAsset.sizeFilled.value * - tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage / 100 - - calculatedBasedOnTradingSystem = true - } - - if (tradingEngineOrder.orderQuotedAsset.feesPaid.value === tradingEngineOrder.orderQuotedAsset.feesPaid.config.initialValue) { - - tradingEngineOrder.orderQuotedAsset.feesPaid.value = - tradingEngineOrder.orderQuotedAsset.sizeFilled.value * - tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage / 100 - - calculatedBasedOnTradingSystem = true - } - } - } - - /* Based on the Session Parameters Definition */ - if (calculatedBasedOnTradingSystem === false) { - /* Fees are simulated based on the Session Paremeters */ - switch (tradingEngineOrder.type) { - case 'Market Order': { - - tradingEngineOrder.orderBaseAsset.feesPaid.value = - tradingEngineOrder.orderBaseAsset.sizeFilled.value * - bot.SESSION.parameters.feeStructure.config.taker / 100 - - tradingEngineOrder.orderQuotedAsset.feesPaid.value = - tradingEngineOrder.orderQuotedAsset.sizeFilled.value * - bot.SESSION.parameters.feeStructure.config.taker / 100 - - break - } - case 'Limit Order': { - - tradingEngineOrder.orderBaseAsset.feesPaid.value = - tradingEngineOrder.orderBaseAsset.sizeFilled.value * - bot.SESSION.parameters.feeStructure.config.maker / 100 - - tradingEngineOrder.orderQuotedAsset.feesPaid.value = - tradingEngineOrder.orderQuotedAsset.sizeFilled.value * - bot.SESSION.parameters.feeStructure.config.maker / 100 - - break - } - } - } - tradingEngineOrder.orderBaseAsset.feesPaid.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.feesPaid.value, 10) - tradingEngineOrder.orderQuotedAsset.feesPaid.value = global.PRECISE(tradingEngineOrder.orderQuotedAsset.feesPaid.value, 10) - } - function percentageFilledSimulation() { /* Order Filling Simulation: the way we are going to handle this is the following. @@ -514,6 +453,14 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM } break } + case 'Market Buy Order': { + orderWasHit = true + break + } + case 'Market Sell Order': { + orderWasHit = true + break + } } if (orderWasHit === true) { if (tradingSystemOrder.simulatedExchangeEvents.simulatedPartialFill !== undefined) { @@ -546,6 +493,80 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM } } + function feesPaidSimulation() { + /* + The way the fess paid is calculated is as follows: From the order size we apply the % of fee, + that would give us the total fees for that order. To that we apply the % filled of the orders, + that give use the final result of the fees paid for the current % filled. + + But before that, we will see if there is an specific definition on how to simulate the fees for + this order, or if there is not, we use the fees session parameters definitions. + */ + let calculatedBasedOnTradingSystem = false + + /* Based on the Trading System Definition */ + if (tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid !== undefined) { + if (tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage !== undefined) { + if (tradingEngineOrder.orderBaseAsset.feesPaid.value === tradingEngineOrder.orderBaseAsset.feesPaid.config.initialValue) { + + tradingEngineOrder.orderBaseAsset.feesPaid.value = + tradingEngineOrder.orderBaseAsset.size.value * + tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + calculatedBasedOnTradingSystem = true + } + + if (tradingEngineOrder.orderQuotedAsset.feesPaid.value === tradingEngineOrder.orderQuotedAsset.feesPaid.config.initialValue) { + + tradingEngineOrder.orderQuotedAsset.feesPaid.value = + tradingEngineOrder.orderQuotedAsset.size.value * + tradingSystemOrder.simulatedExchangeEvents.simulatedFeesPaid.config.percentage / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + calculatedBasedOnTradingSystem = true + } + } + } + + /* Based on the Session Parameters Definition */ + if (calculatedBasedOnTradingSystem === false) { + /* Fees are simulated based on the Session Paremeters */ + switch (tradingEngineOrder.type) { + case 'Market Order': { + + tradingEngineOrder.orderBaseAsset.feesPaid.value = + tradingEngineOrder.orderBaseAsset.size.value * + bot.SESSION.parameters.feeStructure.config.taker / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + tradingEngineOrder.orderQuotedAsset.feesPaid.value = + tradingEngineOrder.orderQuotedAsset.size.value * + bot.SESSION.parameters.feeStructure.config.taker / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + break + } + case 'Limit Order': { + + tradingEngineOrder.orderBaseAsset.feesPaid.value = + tradingEngineOrder.orderBaseAsset.size.value * + bot.SESSION.parameters.feeStructure.config.maker / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + tradingEngineOrder.orderQuotedAsset.feesPaid.value = + tradingEngineOrder.orderQuotedAsset.size.value * + bot.SESSION.parameters.feeStructure.config.maker / 100 * + tradingEngineOrder.orderStatistics.percentageFilled.value / 100 + + break + } + } + } + tradingEngineOrder.orderBaseAsset.feesPaid.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.feesPaid.value, 10) + tradingEngineOrder.orderQuotedAsset.feesPaid.value = global.PRECISE(tradingEngineOrder.orderQuotedAsset.feesPaid.value, 10) + } + function sizeFilledSimulation() { /* Size Filled */ tradingEngineOrder.orderBaseAsset.sizeFilled.value = diff --git a/LowFrequencyTrading/TradingPosition.js b/LowFrequencyTrading/TradingPosition.js index fc1cebcfe..15214c844 100644 --- a/LowFrequencyTrading/TradingPosition.js +++ b/LowFrequencyTrading/TradingPosition.js @@ -104,14 +104,12 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng tradingEngine.current.position.takeProfit.value = formulas.get(formulaId) } - function updateStopLoss(phase, stage) { + function updateStopLoss(phase) { tradingEngine.current.position.stopLoss.stopLossPhase.value = phase - tradingEngine.current.position.stopLoss.stopLossStage.value = stage } - function updateTakeProfit(phase, stage) { + function updateTakeProfit(phase) { tradingEngine.current.position.takeProfit.takeProfitPhase.value = phase - tradingEngine.current.position.takeProfit.takeProfitStage.value = stage } function initialTargets(tradingSystemStageNode, tradingEngineStageNode) { diff --git a/LowFrequencyTrading/TradingStages.js b/LowFrequencyTrading/TradingStages.js index 2c2abf525..79007509b 100644 --- a/LowFrequencyTrading/TradingStages.js +++ b/LowFrequencyTrading/TradingStages.js @@ -545,7 +545,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingSystem.highlights.push(parentNode.id) tradingSystem.highlights.push(manageStage.id) - tradingPositionModule.updateStopLoss(tradingEngine.current.position.stopLoss.stopLossPhase.value + 1, 'Manage Stage') + tradingPositionModule.updateStopLoss(tradingEngine.current.position.stopLoss.stopLossPhase.value + 1) announcementsModule.makeAnnoucements(nextPhaseEvent) return // only one event can pass at the time @@ -579,7 +579,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM if (moveToPhase !== undefined) { for (let q = 0; q < stopLoss.phases.length; q++) { if (stopLoss.phases[q].id === moveToPhase.id) { - tradingPositionModule.updateStopLoss(q + 1, 'Manage Stage') + tradingPositionModule.updateStopLoss(q + 1) } } } else { @@ -638,7 +638,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingSystem.highlights.push(parentNode.id) tradingSystem.highlights.push(manageStage.id) - tradingPositionModule.updateTakeProfit(tradingEngine.current.position.takeProfit.takeProfitPhase.value + 1, 'Manage Stage') + tradingPositionModule.updateTakeProfit(tradingEngine.current.position.takeProfit.takeProfitPhase.value + 1) announcementsModule.makeAnnoucements(nextPhaseEvent) return // only one event can pass at the time @@ -672,7 +672,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM if (moveToPhase !== undefined) { for (let q = 0; q < takeProfit.phases.length; q++) { if (takeProfit.phases[q].id === moveToPhase.id) { - tradingPositionModule.updateTakeProfit(q + 1, 'Manage Stage') + tradingPositionModule.updateTakeProfit(q + 1) } } } else { @@ -769,7 +769,13 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM The reason for that is that we need the final filled size of the Open Stage to be known before we start placing orders at the Close Stage. */ - if (tradingEngine.current.strategyCloseStage.status.value === 'Open' && tradingEngine.current.strategyOpenStage.status.value === 'Closed') { + if ( + tradingEngine.current.strategyCloseStage.status.value === 'Open' && + ( + tradingEngine.current.strategyOpenStage.status.value === 'Closed' || + tradingEngine.current.strategyOpenStage.status.value == tradingEngine.current.strategyOpenStage.status.config.initialValue + ) + ) { /* This will happen as long as the Close Stage is Open. */ @@ -878,7 +884,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM if ( tradingEngineStage.stageBaseAsset.sizeFilled.value + tradingEngineStage.stageBaseAsset.feesPaid.value >= - tradingEngineStage.stageBaseAsset.targetSize + tradingEngineStage.stageBaseAsset.targetSize.value ) { positionFilled() } else { @@ -890,7 +896,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM if ( tradingEngineStage.stageQuotedAsset.sizeFilled.value + tradingEngineStage.stageQuotedAsset.feesPaid.value >= - tradingEngineStage.stageQuotedAsset.targetSize + tradingEngineStage.stageQuotedAsset.targetSize.value ) { positionFilled() } else { @@ -970,33 +976,33 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM function openStage(stage) { /* Recording the opening at the Trading Engine Data Structure */ - stage.begin.value = tradingEngine.current.episode.candle.end.value + stage.begin.value = tradingEngine.current.episode.cycle.begin.value stage.beginRate.value = tradingEngine.current.episode.candle.close.value - stage.end.value = tradingEngine.current.episode.candle.end.value + stage.end.value = tradingEngine.current.episode.cycle.end.value } function closeStage(stage) { /* Recording the closing at the Trading Engine Data Structure */ - stage.end.value = tradingEngine.current.episode.candle.end.value + stage.end.value = tradingEngine.current.episode.cycle.end.value stage.endRate.value = tradingEngine.current.episode.candle.close.value } } function updateEnds() { if (tradingEngine.current.strategyTriggerStage.status.value === 'Open') { - tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.episode.candle.end.value + tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.episode.cycle.end.value tradingEngine.current.strategyTriggerStage.endRate.value = tradingEngine.current.episode.candle.close.value } if (tradingEngine.current.strategyOpenStage.status.value === 'Open') { - tradingEngine.current.strategyOpenStage.end.value = tradingEngine.current.episode.candle.end.value + tradingEngine.current.strategyOpenStage.end.value = tradingEngine.current.episode.cycle.end.value tradingEngine.current.strategyOpenStage.endRate.value = tradingEngine.current.episode.candle.close.value } if (tradingEngine.current.strategyManageStage.status.value === 'Open') { - tradingEngine.current.strategyManageStage.end.value = tradingEngine.current.episode.candle.end.value + tradingEngine.current.strategyManageStage.end.value = tradingEngine.current.episode.cycle.end.value tradingEngine.current.strategyManageStage.endRate.value = tradingEngine.current.episode.candle.close.value } if (tradingEngine.current.strategyCloseStage.status.value === 'Open') { - tradingEngine.current.strategyCloseStage.end.value = tradingEngine.current.episode.candle.end.value + tradingEngine.current.strategyCloseStage.end.value = tradingEngine.current.episode.cycle.end.value tradingEngine.current.strategyCloseStage.endRate.value = tradingEngine.current.episode.candle.close.value } } diff --git a/Session.js b/Session.js index 6f627e326..58e944b15 100644 --- a/Session.js +++ b/Session.js @@ -160,6 +160,20 @@ finalDatetime: (new Date()).valueOf() } } + } else { + /* Check that we received valid dates */ + if(isNaN(new Date(bot.SESSION.parameters.timeRange.config.initialDatetime)).valueOf()) { + let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date." + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage) + bot.sessionError(bot.SESSION.parameters, errorMessage) + return false + } + if(isNaN(new Date(bot.SESSION.parameters.timeRange.config.finalDatetime)).valueOf()) { + let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date." + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage) + bot.sessionError(bot.SESSION.parameters, errorMessage) + return false + } } /* Session Type Forced Values */