diff --git a/LowFrequencyTrading/ExchangeAPI.js b/LowFrequencyTrading/ExchangeAPI.js index 8d6adc9a1..633f9a59c 100644 --- a/LowFrequencyTrading/ExchangeAPI.js +++ b/LowFrequencyTrading/ExchangeAPI.js @@ -63,7 +63,7 @@ } try { - let order = await (exchange.fetchOrder(orderId, symbol)) + let order = await exchange.fetchOrder(orderId, symbol) return order } catch (err) { tradingSystem.errors.push([tradingSystemOrder.id, err.message]) @@ -144,7 +144,7 @@ } try { - let order = await (exchange.cancelOrder(orderId, symbol)) + let order = await exchange.cancelOrder(orderId, symbol) return true } catch (err) { tradingSystem.errors.push([tradingSystemOrder.id, err.message]) diff --git a/LowFrequencyTrading/TradingExecution.js b/LowFrequencyTrading/TradingExecution.js index 2b6d89777..3aed57b8c 100644 --- a/LowFrequencyTrading/TradingExecution.js +++ b/LowFrequencyTrading/TradingExecution.js @@ -43,26 +43,26 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE announcementsModule = undefined } - function checkExecution(executionNode, stageIsOpening, stageIsClosing, stageSizeLimit, stageOrdersSize, stageFilledSize) { + async function checkExecution(executionNode, stageIsOpening, stageIsClosing, stageSizeLimit, stageOrdersSize, stageFilledSize) { /* Enforcing Precision Limit */ stageSizeLimit.value = global.PRECISE(stageSizeLimit.value, 10) stageOrdersSize.value = global.PRECISE(stageOrdersSize.value, 10) stageFilledSize.value = global.PRECISE(stageFilledSize.value, 10) - checkExecutionAlgorithms(executionNode) + await checkExecutionAlgorithms(executionNode) - function checkExecutionAlgorithms(executionNode) { + async function checkExecutionAlgorithms(executionNode) { for (let i = 0; i < executionNode.executionAlgorithms.length; i++) { let executionAlgorithm = executionNode.executionAlgorithms[i] - checkOrders(executionAlgorithm.marketBuyOrders, executionAlgorithm, executionNode) - checkOrders(executionAlgorithm.marketSellOrders, executionAlgorithm, executionNode) - checkOrders(executionAlgorithm.limitBuyOrders, executionAlgorithm, executionNode) - checkOrders(executionAlgorithm.limitSellOrders, executionAlgorithm, executionNode) + await checkOrders(executionAlgorithm.marketBuyOrders, executionAlgorithm, executionNode) + await checkOrders(executionAlgorithm.marketSellOrders, executionAlgorithm, executionNode) + await checkOrders(executionAlgorithm.limitBuyOrders, executionAlgorithm, executionNode) + await checkOrders(executionAlgorithm.limitSellOrders, executionAlgorithm, executionNode) } } - function checkOrders(orders, executionAlgorithm, executionNode) { + async function checkOrders(orders, executionAlgorithm, executionNode) { for (let i = 0; i < orders.length; i++) { let tradingSystemOrder = orders[i] @@ -99,7 +99,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE if (situationName !== undefined) { /* Open a new order */ - openOrder(executionAlgorithm, tradingSystemOrder, tradingEngineOrder, situationName) + await openOrder(executionAlgorithm, tradingSystemOrder, tradingEngineOrder, situationName) } } break @@ -113,7 +113,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE simulateExchangeEvents(tradingSystemOrder, tradingEngineOrder) /* Check Events that happens at the Exchange, if needed. */ - checkExchangeEvents(tradingSystemOrder, tradingEngineOrder) + await checkExchangeEvents(tradingSystemOrder, tradingEngineOrder) /* If the stage is closing or the order is not still Open, we wont be cancelling orders based on defined events */ if (stageIsClosing !== true && tradingEngineOrder.status.value === 'Open') { @@ -122,7 +122,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE let situationName = checkOrderEvent(tradingSystemOrder.cancelOrderEvent, tradingSystemOrder, executionAlgorithm, executionNode) if (situationName !== undefined) { simulateCancelOrder(tradingSystemOrder, tradingEngineOrder, 'Cancel Event') - exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, 'Cancel Event') + await exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, 'Cancel Event') } } } @@ -130,7 +130,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } } - function openOrder(executionAlgorithm, tradingSystemOrder, tradingEngineOrder, situationName) { + async function openOrder(executionAlgorithm, tradingSystemOrder, tradingEngineOrder, situationName) { /* Order Size Calculation */ tradingEngineOrder.size.value = tradingSystem.formulas.get(executionAlgorithm.positionSize.formula.id) * tradingSystemOrder.config.positionSizePercentage / 100 if (stageOrdersSize.value + tradingEngineOrder.size.value > stageSizeLimit.value) { @@ -152,7 +152,8 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } /* Place Order at the Exchange */ - if (createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) !== true) { return } + let result = await createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) + if (result !== true) { return } /* Updating Episode Counters */ tradingEngine.episode.episodeCounters.orders.value++ @@ -271,7 +272,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } } - function checkExchangeEvents(tradingSystemOrder, tradingEngineOrder) { + async function checkExchangeEvents(tradingSystemOrder, tradingEngineOrder) { /* Filter by Session Type */ switch (bot.SESSION.type) { @@ -289,7 +290,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } } - let order = exchangeAPIModule.getOrder(tradingSystemOrder, tradingEngineOrder) + let order = await exchangeAPIModule.getOrder(tradingSystemOrder, tradingEngineOrder) if (order === undefined) { return } @@ -300,7 +301,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } /* Status Checks */ - if (tradingEngineOrder.orderStatistics.percentageFilled.value === 100 && order.status === AT_EXCHANGE_STATUS.CLOSED) { + if (order.remaining === 0 && order.status === AT_EXCHANGE_STATUS.CLOSED) { /* Close this Order */ tradingEngineOrder.status.value = 'Closed' @@ -309,7 +310,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE /* Initialize this */ tradingEngine.current.distanceToEvent.closeOrder.value = 1 } - if (tradingEngineOrder.orderStatistics.percentageFilled.value < 100 && order.status === AT_EXCHANGE_STATUS.CLOSED) { + if (order.remaining > 0 && order.status === AT_EXCHANGE_STATUS.CLOSED) { /* Close this Order */ tradingEngineOrder.status.value = 'Closed' @@ -332,14 +333,14 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE /* Forced Cancellation Check */ if (stageIsClosing === true && tradingEngineOrder.status.value !== 'Closed') { - exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, 'Closing Stage') + await exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, 'Closing Stage') } } function syncWithExchange(tradingSystemOrder, tradingEngineOrder, order) { /* Percentage Filled */ let currentPercentageFilled = tradingEngineOrder.orderStatistics.percentageFilled.value - let percentageFilled = order.filled * 100 / tradingEngineOrder.size + let percentageFilled = order.filled * 100 / (order.filled + order.remaining) percentageFilled = global.PRECISE(percentageFilled.value, 10) tradingEngineOrder.orderStatistics.percentageFilled.value = percentageFilled @@ -348,12 +349,12 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE stageFilledSize.value = stageFilledSize.value + tradingEngineOrder.size.value * percentageFilled / 100 // Second add the new filled size stageFilledSize.value = global.PRECISE(stageFilledSize.value, 10) - /* Actual Rate Simulation */ - tradingEngineOrder.orderStatistics.actualRate.value = order.cost / order.filled + /* Actual Rate Calculation */ + tradingEngineOrder.orderStatistics.actualRate.value = order.price tradingEngineOrder.orderStatistics.actualRate.value = global.PRECISE(tradingEngineOrder.orderStatistics.actualRate.value, 10) - /* Fees Paid Simulation */ - tradingEngineOrder.orderStatistics.feesPaid.value = order.fee.rate + /* Fees Paid Calculation */ + tradingEngineOrder.orderStatistics.feesPaid.value = tradingEngineOrder.size.value - order.amount tradingEngineOrder.orderStatistics.feesPaid.value = global.PRECISE(tradingEngineOrder.orderStatistics.feesPaid.value, 10) } @@ -389,7 +390,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE stageOrdersSize.value = global.PRECISE(stageOrdersSize.value, 10) } - function exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, exitType) { + async function exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder, exitType) { /* Filter by Session Type */ switch (bot.SESSION.type) { @@ -408,7 +409,8 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } /* Check if we can cancel the order at the Exchange. */ - if (exchangeAPIModule.exchangeCancelOrder(tradingSystemOrder, tradingEngineOrder) === true) { + let result = await exchangeAPIModule.cancelOrder(tradingSystemOrder, tradingEngineOrder) + if (result === true) { /* Close this Order */ tradingEngineOrder.status.value = 'Closed' tradingEngineOrder.exitType.value = exitType @@ -427,16 +429,10 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE To sync our accounting, we need to check the order one last time and if it changed, fix it. */ - let order = exchangeAPIModule.getOrder(tradingSystemOrder, tradingEngineOrder) + let order = await exchangeAPIModule.getOrder(tradingSystemOrder, tradingEngineOrder) if (order === undefined) { return } - const AT_EXCHANGE_STATUS = { - OPEN: 'open', - CLOSED: 'closed', - CANCELLED: 'canceled' - } - syncWithExchange(tradingSystemOrder, tradingEngineOrder, order) } } diff --git a/LowFrequencyTrading/TradingSimulation.js b/LowFrequencyTrading/TradingSimulation.js index 045f353d7..58470f756 100644 --- a/LowFrequencyTrading/TradingSimulation.js +++ b/LowFrequencyTrading/TradingSimulation.js @@ -108,7 +108,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT loop() } - function loop() { + async function loop() { if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Processing candle # ' + tradingEngine.current.candle.index.value) } let candle = candles[tradingEngine.current.candle.index.value] // This is the current candle the Simulation is working at. @@ -146,13 +146,13 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT tradingSystemModule.triggerStage() /* Run the Open Stage */ - tradingSystemModule.openStage() + await tradingSystemModule.openStage() /* Run the Manage Stage */ tradingSystemModule.manageStage() /* Run the Close Stage */ - tradingSystemModule.closeStage() + await tradingSystemModule.closeStage() /* Add new records to the process output */ tradingRecordsModule.appendRecords() diff --git a/LowFrequencyTrading/TradingSystem.js b/LowFrequencyTrading/TradingSystem.js index 6ca9b3852..7cb87893c 100644 --- a/LowFrequencyTrading/TradingSystem.js +++ b/LowFrequencyTrading/TradingSystem.js @@ -504,7 +504,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM } } - function openStage() { + async function openStage() { /* Abort Open Stage Check */ if (tradingEngine.current.strategy.openStageStatus.value === 'Open' && tradingEngine.current.strategy.closeStageStatus.value === 'Open') { /* @@ -538,7 +538,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Open Execution') evalFormulas(stageNode, 'Open Execution') - tradingExecutionModule.checkExecution(executionNode, true, false, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) + await tradingExecutionModule.checkExecution(executionNode, true, false, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) /* From here on, the state is officially Open */ tradingStrategyModule.updateStageStatus('Open Stage', 'Open') @@ -558,7 +558,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Open Execution') evalFormulas(stageNode, 'Open Execution') - tradingExecutionModule.checkExecution(executionNode, false, false, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) + await tradingExecutionModule.checkExecution(executionNode, false, false, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) /* The Open is finished when the fillSize reaches the Position Size. @@ -586,7 +586,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Open Execution') evalFormulas(stageNode, 'Open Execution') - tradingExecutionModule.checkExecution(executionNode, false, true, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) + await tradingExecutionModule.checkExecution(executionNode, false, true, tradingEngine.current.position.size, tradingEngine.current.position.openStageOrdersSize, tradingEngine.current.position.openStageFilledSize) } /* @@ -948,7 +948,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM } } - function closeStage() { + async function closeStage() { /* Opening Status Procedure */ if (tradingEngine.current.strategy.closeStageStatus.value === 'Opening') { /* @@ -972,7 +972,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Close Execution') evalFormulas(stageNode, 'Close Execution') - tradingExecutionModule.checkExecution(executionNode, false, false, tradingEngine.current.position.openStageFilledSize, tradingEngine.current.position.closeStageOrdersSize, tradingEngine.current.position.closeStageFilledSize) + await tradingExecutionModule.checkExecution(executionNode, false, false, tradingEngine.current.position.openStageFilledSize, tradingEngine.current.position.closeStageOrdersSize, tradingEngine.current.position.closeStageFilledSize) /* Close the Stage Validation */ if (tradingEngine.current.position.closeStageFilledSize.value === tradingEngine.current.position.openStageFilledSize.value) {