diff --git a/LowFrequencyTrading/ExchangeAPI.js b/LowFrequencyTrading/ExchangeAPI.js index 633f9a59c..3c4861120 100644 --- a/LowFrequencyTrading/ExchangeAPI.js +++ b/LowFrequencyTrading/ExchangeAPI.js @@ -74,10 +74,20 @@ async function createOrder(tradingSystemOrder, tradingEngineOrder) { let price = tradingEngineOrder.rate.value // CCXT: how much quote currency you are willing to pay for a trade lot of base currency (for limit orders only) - let amount = tradingEngineOrder.size.value // CCXT: how much of currency you want to trade let type // CCXT: a string literal type of order, ccxt currently unifies market and limit orders only let side // CCXT: a string literal for the direction of your order, buy or sell let symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset // CCXT: a string literal symbol of the market you wish to trade on, like BTC/USD, ZEC/ETH, DOGE/DASH, etc + let amount // CCXT: how much of currency you want to trade + + /* + We need at the amount a value denominated in Base Asset, if we do not + have it, then we convert the value we have in Quoteed Asset. + */ + if (tradingEngineOrder.orderBaseAsset.size.value > 0) { + amount = tradingEngineOrder.orderBaseAsset.size.value + } else { + amount = tradingEngineOrder.orderQuotedAsset.size.value / tradingEngineOrder.rate.value + } switch (tradingSystemOrder.type) { case 'Market Buy Order': { diff --git a/LowFrequencyTrading/TradingExecution.js b/LowFrequencyTrading/TradingExecution.js index 0d36253fc..f074e96f4 100644 --- a/LowFrequencyTrading/TradingExecution.js +++ b/LowFrequencyTrading/TradingExecution.js @@ -47,18 +47,45 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE executionNode, stageIsOpening, stageIsClosing, - stageSizeLimit, - stageOrdersSizeInBaseAsset, - stageFilledSizeInBaseAsset, - stageOrdersSizeInQuotedAsset, - stageFilledSizeInQuotedAsset + stageSizeLimitInBaseAsset, + stageSizeLimitInQuotedAsset, + tradingEngineStage ) { - /* Enforcing Precision Limit */ - stageOrdersSizeInBaseAsset.value = global.PRECISE(stageOrdersSizeInBaseAsset.value, 10) - stageOrdersSizeInBaseAsset.value = global.PRECISE(stageOrdersSizeInBaseAsset.value, 10) - stageOrdersSizeInQuotedAsset.value = global.PRECISE(stageOrdersSizeInQuotedAsset.value, 10) - stageFilledSizeInQuotedAsset.value = global.PRECISE(stageFilledSizeInQuotedAsset.value, 10) + /* Trading Stage Validations */ + if (tradingEngineStage.stageBaseAsset === undefined) { continue } + if (tradingEngineStage.stageBaseAsset.size === undefined) { continue } + if (tradingEngineStage.stageBaseAsset.sizeFilled === undefined) { continue } + if (tradingEngineStage.stageBaseAsset.amountReceived === undefined) { continue } + if (tradingEngineStage.stageBaseAsset.feesPaid === undefined) { continue } + if (tradingEngineStage.stageQuotedAsset === undefined) { continue } + if (tradingEngineStage.stageQuotedAsset.size === undefined) { continue } + if (tradingEngineStage.stageQuotedAsset.sizeFilled === undefined) { continue } + if (tradingEngineStage.stageQuotedAsset.amountReceived === undefined) { continue } + if (tradingEngineStage.stageQuotedAsset.feesPaid === undefined) { continue } + + /* + The user choice of asset to define the size of the position, + defines the asset that will track the information kept about the + stage at the trading engine data structure. We set this asset + to be used here in this way: + */ + let tradingEngineStageAsset + if (tradingEngine.current.position.positionBaseAsset.size.value > 0) { + tradingEngineStageAsset = tradingEngineStage.stageBaseAsset + } else { + tradingEngineStageAsset = tradingEngineStage.stageQuotedAsset + } + /* + The asset type of the position size chosen by the user, also defines + the stage limit to be on the same asset type. + */ + let stageSizeLimit + if (tradingEngine.current.position.positionBaseAsset.size.value > 0) { + stageSizeLimit = stageSizeLimitInBaseAsset + } else { + stageSizeLimit = stageSizeLimitInQuotedAsset + } await checkExecutionAlgorithms(executionNode) @@ -90,7 +117,6 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE if (tradingEngineOrder.begin === undefined) { continue } if (tradingEngineOrder.end === undefined) { continue } if (tradingEngineOrder.rate === undefined) { continue } - if (tradingEngineOrder.size === undefined) { continue } if (tradingEngineOrder.status === undefined) { continue } if (tradingEngineOrder.algorithmName === undefined) { continue } if (tradingEngineOrder.orderCounters === undefined) { continue } @@ -100,9 +126,33 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE if (tradingEngineOrder.orderStatistics.actualRate === undefined) { continue } if (tradingEngineOrder.orderStatistics.feesPaid === undefined) { continue } + if (tradingEngineOrder.orderBaseAsset.size === undefined) { continue } + if (tradingEngineOrder.orderBaseAsset.sizeFilled === undefined) { continue } + if (tradingEngineOrder.orderBaseAsset.amountReceived === undefined) { continue } + if (tradingEngineOrder.orderBaseAsset.feesPaid === undefined) { continue } + + if (tradingEngineOrder.orderQuotedAsset.size === undefined) { continue } + if (tradingEngineOrder.orderQuotedAsset.sizeFilled === undefined) { continue } + if (tradingEngineOrder.orderQuotedAsset.amountReceived === undefined) { continue } + if (tradingEngineOrder.orderQuotedAsset.feesPaid === undefined) { continue } + + /* + The asset type of the position size chosen by the user, defines + the asset at the order data strutcture where information is going to + be stored. + */ + let traingEngineOrderAsset + if (tradingEngine.current.position.positionBaseAsset.size.value > 0) { + traingEngineOrderAsset = tradingEngineOrder.orderBaseAsset + } else { + traingEngineOrderAsset = tradingEngineOrder.orderQuotedAsset + } + switch (tradingEngineOrder.status.value) { case 'Not Open': { { + /* When the stage is closing we can not create new orders */ + if (stageIsClosing === true) { continue } /* Check if we can create an order based on the config value for spawnMultipleOrders. Trading System Orders that cannot spawn more than one Trading Engine Order needs to check if @@ -114,7 +164,6 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } } /* Check if we need to Create this Order */ - if (stageIsClosing === true) { continue } let situationName = checkOrderEvent(tradingSystemOrder.createOrderEvent, tradingSystemOrder, executionAlgorithm, executionNode) if (situationName !== undefined) { @@ -151,32 +200,22 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE } async function openOrder(executionAlgorithm, tradingSystemOrder, tradingEngineOrder, situationName) { - /* Order Size Calculation */ - let positionSize = tradingSystem.formulas.get(executionAlgorithm.positionSize.formula.id) - if (positionSize === undefined) { return } - tradingEngineOrder.size.value = positionSize * tradingSystemOrder.config.positionSizePercentage / 100 - if (stageOrdersSize.value + tradingEngineOrder.size.value > stageSizeLimit.value) { - /* We reduce the size to the remaining size of the position. */ - tradingEngineOrder.size.value = stageSizeLimit.value - stageOrdersSize.value - tradingEngineOrder.size.value = global.PRECISE(tradingEngineOrder.size.value, 10) - } - /* Check Order Size */ - if (tradingEngineOrder.size.value <= 0) { return } + calculateOrderSize() - /* Order Rate Calculation */ - tradingEngineOrder.rate.value = tradingEngine.current.position.rate.value // By default this is the order rate. - if (tradingSystemOrder.positionRate !== undefined) { - if (tradingSystemOrder.positionRate.formula !== undefined) { - tradingEngineOrder.rate.value = tradingSystem.formulas.get(tradingSystemOrder.positionRate.formula.id) - tradingEngineOrder.rate.value = global.PRECISE(tradingEngineOrder.rate.value, 10) - } - } + /* Check Size: We are not going to create Orders which size is equal or less to zero. */ + if (traingEngineOrderAsset.size.value <= 0) { return } + + calculateOrderRate() /* Place Order at the Exchange */ let result = await createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) if (result !== true) { return } + /* Update Stage Counters */ + tradingEngineStageAsset.value = tradingEngineStageAsset.value + tradingEngineOrder.size.value + tradingEngineStageAsset.value = global.PRECISE(tradingEngineStageAsset.value, 10) + /* Updating Episode Counters */ tradingEngine.episode.episodeCounters.orders.value++ @@ -193,9 +232,93 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE tradingEngineOrder.algorithmName.value = executionAlgorithm.name tradingEngineOrder.situationName.value = situationName - /* Update Stage Orders Size */ - stageOrdersSize.value = stageOrdersSize.value + tradingEngineOrder.size.value - stageOrdersSize.value = global.PRECISE(stageOrdersSize.value, 10) + function calculateOrderSize() { + /* + If the position size was defined in Base Asset, then + the algorithm needs to define its size also in Base Asset. + The same if it was deined in Quoted Asset. + */ + let sizeFormula + if (tradingEngine.current.position.positionBaseAsset.size.value > 0) { + /* Position was defined in Base Asset */ + if (executionAlgorithm.sizeInBaseAsset !== undefined) { + if (executionAlgorithm.sizeInBaseAsset.formula !== undefined) { + sizeFormula = executionAlgorithm.sizeInBaseAsset.formula + } else { + const errorText = 'Size In Base Asset needs a child Formula. Fix this please.' + tradingSystem.errors.push([executionAlgorithm.sizeInBaseAsset.id, errorText]) + throw (errorText) + } + } else { + const errorText = 'Execution Algorithm needs a child Size In Base Asset. Fix this please.' + tradingSystem.errors.push([executionAlgorithm.id, errorText]) + throw (errorText) + } + } else { + /* Position was defined in Quoted Asset */ + if (executionAlgorithm.sizeInQuotedAsset !== undefined) { + if (executionAlgorithm.sizeInQuotedAsset.formula !== undefined) { + sizeFormula = executionAlgorithm.sizeInQuotedAsset.formula + } else { + const errorText = 'Size In Quoted Asset needs a child Formula. Fix this please.' + tradingSystem.errors.push([executionAlgorithm.sizeInQuotedAsset.id, errorText]) + throw (errorText) + } + } else { + const errorText = 'Execution Algorithm needs a child Size In Quoted Asset. Fix this please.' + tradingSystem.errors.push([executionAlgorithm.id, errorText]) + throw (errorText) + } + } + + /* Order Size Calculation */ + let algorithmSize = tradingSystem.formulas.get(sizeFormula.id) + if (algorithmSize === undefined) { + const errorText = 'Execution Algorithm Size cannot be undefined. Fix this please.' + tradingSystem.errors.push([sizeFormula.id, errorText]) + throw (errorText) + } + + /* Validate that this config exists */ + if (tradingSystemOrder.config.positionSizePercentage === undefined) { + const errorText = 'Config positionSizePercentage does not exist. Fix this please.' + tradingSystem.errors.push([tradingSystemOrder.id, errorText]) + throw (errorText) + } + + traingEngineOrderAsset.size.value = algorithmSize * tradingSystemOrder.config.positionSizePercentage / 100 + traingEngineOrderAsset.size.value = global.PRECISE(traingEngineOrderAsset.size.value, 10) + + /* Check against the Stage Size Limit */ + if (tradingEngineStageAsset.size.value + traingEngineOrderAsset.size.value > stageSizeLimit.value) { + /* We reduce the size to the remaining size of the position. */ + traingEngineOrderAsset.size.value = stageSizeLimit.value - tradingEngineStageAsset.value + traingEngineOrderAsset.size.value = global.PRECISE(traingEngineOrderAsset.size.value, 10) + } + } + + function calculateOrderRate() { + /* Order Rate Calculation */ + tradingEngineOrder.rate.value = tradingEngine.current.position.rate.value // By default this is the order rate. + if (tradingSystemOrder.positionRate !== undefined) { + if (tradingSystemOrder.positionRate.formula !== undefined) { + tradingEngineOrder.rate.value = tradingSystem.formulas.get(tradingSystemOrder.positionRate.formula.id) + + if (tradingEngineOrder.rate.value === undefined) { + const errorText = 'Rate cannot be undefined. Fix this please.' + tradingSystem.errors.push([tradingSystemOrder.positionRate.formula.id, errorText]) + throw (errorText) + } + + if (tradingEngineOrder.rate.value <= 0) { + const errorText = 'Rate cannot be less or equal to zero. Fix this please.' + tradingSystem.errors.push([tradingSystemOrder.positionRate.formula.id, errorText]) + throw (errorText) + } + tradingEngineOrder.rate.value = global.PRECISE(tradingEngineOrder.rate.value, 10) + } + } + } } async function createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) { diff --git a/LowFrequencyTrading/TradingPosition.js b/LowFrequencyTrading/TradingPosition.js index c7ac8a39d..0f1d3e074 100644 --- a/LowFrequencyTrading/TradingPosition.js +++ b/LowFrequencyTrading/TradingPosition.js @@ -15,7 +15,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng applySlippageToTakeProfit: applySlippageToTakeProfit, updateStopLoss: updateStopLoss, updateTakeProfit: updateTakeProfit, - updateSizeAndRate: updateSizeAndRate, + initializeSizeAndRate: initializeSizeAndRate, updateEnds: updateEnds, updateStatus: updateStatus, updateCounters: updateCounters, @@ -41,18 +41,26 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng } function openPosition(situationName) { + + /* Recording the opening at the Trading Engine Data Structure */ tradingEngine.current.position.status.value = 'Open' tradingEngine.current.position.serialNumber.value = tradingEngine.episode.episodeCounters.positions.value tradingEngine.current.position.identifier.value = global.UNIQUE_ID() tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value - tradingEngine.current.position.situationName.value = situationName + /* Initializing Stop and Take Profit Stage / Phase */ tradingEngine.current.position.stopLoss.stopLossStage.value = 'Open Stage' tradingEngine.current.position.takeProfit.takeProfitStage.value = 'Open Stage' tradingEngine.current.position.stopLoss.stopLossPhase.value = 0 tradingEngine.current.position.takeProfit.takeProfitPhase.value = 0 + + /* Updating Episode Counters */ + tradingEngine.episode.episodeCounters.positions.value++ + + /* Inicializing this counter */ + tradingEngine.current.distanceToEvent.takePosition.value = 1 } function closingPosition(exitType) { @@ -91,11 +99,84 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng tradingEngine.current.position.takeProfit.takeProfitStage.value = stage } - function updateSizeAndRate(size, rate) { - tradingEngine.current.position.size.value = global.PRECISE(size, 10) - tradingEngine.current.position.rate.value = global.PRECISE(rate, 10) + function initializeSizeAndRate() { + + setPositionSize() + setPositionRate() tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value + + function setPositionSize() { + let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value] + + /* Basic Validation */ + if ( + strategy.openStage.initialDefinition.positionSizeInBaseAsset !== undefined && + strategy.openStage.initialDefinition.positionSizeInQuotedAsset !== undefined + ) { + const errorText = 'Only Position Size In Base Asset or Position Size In Quoted Asset is allowed. Remove one of them please.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.id, errorText]) + throw (errorText) + } + + /* Position In Base Asset */ + if (strategy.openStage.initialDefinition.positionSizeInBaseAsset !== undefined) { + if (strategy.openStage.initialDefinition.positionSizeInBaseAsset.formula !== undefined) { + let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionSizeInBaseAsset.formula.id) + if (value === undefined) { + const errorText = 'Position Size In Base Asset cannot be undefined. Fix this please.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInBaseAsset.formula.id, errorText]) + throw (errorText) + } + if (value === undefined) { + const errorText = 'Position Size In Base Asset cannot be zero. Fix this please.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInBaseAsset.formula.id, errorText]) + throw (errorText) + } + tradingEngine.current.position.positionBaseAsset.size.value = global.PRECISE(value, 10) + } else { + const errorText = 'You need to specify a Formula for this.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInBaseAsset.id, errorText]) + throw (errorText) + } + } + + /* Position In Quoted Asset */ + if (strategy.openStage.initialDefinition.positionSizeInQuotedAsset !== undefined) { + if (strategy.openStage.initialDefinition.positionSizeInQuotedAsset.formula !== undefined) { + let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionSizeInQuotedAsset.formula.id) + if (value === undefined) { + const errorText = 'Position Size In Quoted Asset cannot be undefined. Fix this please.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInQuotedAsset.formula.id, errorText]) + throw (errorText) + } + if (value === undefined) { + const errorText = 'Position Size In Quoted Asset cannot be zero. Fix this please.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInQuotedAsset.formula.id, errorText]) + throw (errorText) + } + tradingEngine.current.position.positionQuotedAsset.size.value = global.PRECISE(value, 10) + } else { + const errorText = 'You need to specify a Formula for this.' + tradingSystem.errors.push([strategy.openStage.initialDefinition.positionSizeInQuotedAsset.id, errorText]) + throw (errorText) + } + } + } + + function setPositionRate() { + const DEFAULT_VALUE = tradingEngine.current.candle.close.value + let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value] + + if (strategy.openStage === undefined) return DEFAULT_VALUE + if (strategy.openStage.initialDefinition === undefined) return DEFAULT_VALUE + if (strategy.openStage.initialDefinition.positionRate === undefined) return DEFAULT_VALUE + if (strategy.openStage.initialDefinition.positionRate.formula === undefined) return DEFAULT_VALUE + + let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionRate.formula.id) + if (value === undefined) return DEFAULT_VALUE + return value + } } function preventStopLossDistortion() { diff --git a/LowFrequencyTrading/TradingSystem.js b/LowFrequencyTrading/TradingSystem.js index 81790873e..bae1bf683 100644 --- a/LowFrequencyTrading/TradingSystem.js +++ b/LowFrequencyTrading/TradingSystem.js @@ -484,12 +484,6 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM tradingSystem.highlights.push(triggerStage.takePosition.id) tradingSystem.highlights.push(triggerStage.id) - /* Updating Episode Counters */ - tradingEngine.episode.episodeCounters.positions.value++ - - /* Inicializing this counter */ - tradingEngine.current.distanceToEvent.takePosition.value = 1 - tradingPositionModule.openPosition(situation.name) announcementsModule.makeAnnoucements(triggerStage.takePosition) @@ -538,16 +532,14 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Initial Definition') evalFormulas(stageNode, 'Initial Definition') - getReadyToTakePosition() - - calculateTakeProfit() - calculateStopLoss() - /* Remember the balance we had before taking the position to later calculate profit or loss */ tradingEngine.previous.balance.baseAsset.value = tradingEngine.current.balance.baseAsset.value tradingEngine.previous.balance.quotedAsset.value = tradingEngine.current.balance.quotedAsset.value - /* Check Execution in opening stage node */ + /* Position size and rate */ + tradingPositionModule.initializeSizeAndRate() + + /* Check Execution at open stage node */ evalConditions(stageNode, 'Open Execution') evalFormulas(stageNode, 'Open Execution') @@ -555,12 +547,12 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM executionNode, true, false, - tradingEngine.current.position.size, - tradingEngine.current.position.openStageOrdersSize, - tradingEngine.current.position.openStageFilledSize + tradingEngine.current.position.positionBaseAsset.size, // Stage Size Limit + tradingEngine.current.position.positionQuotedAsset.size, // Stage Size Limit + tradingEngine.current.position.strategyOpenStage ) - /* From here on, the state is officially Open */ + /* From here on, the state is officialy Open */ tradingStrategyModule.updateStageStatus('Open Stage', 'Open') return } @@ -582,9 +574,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM executionNode, false, false, - tradingEngine.current.position.size, - tradingEngine.current.position.openStageOrdersSize, - tradingEngine.current.position.openStageFilledSize + tradingEngine.current.position.positionBaseAsset.size, // Stage Size Limit + tradingEngine.current.position.positionQuotedAsset.size, // Stage Size Limit + tradingEngine.current.position.strategyOpenStage ) /* The Open is finished when the fillSize reaches the Position Size. @@ -622,9 +614,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM executionNode, false, true, - tradingEngine.current.position.size, - tradingEngine.current.position.openStageOrdersSize, - tradingEngine.current.position.openStageFilledSize + tradingEngine.current.position.positionBaseAsset.size, // Stage Size Limit + tradingEngine.current.position.positionQuotedAsset.size, // Stage Size Limit + tradingEngine.current.position.strategyOpenStage ) } @@ -644,46 +636,6 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM } } } - - function getReadyToTakePosition() { - - /* Position size and rate */ - tradingPositionModule.updateSizeAndRate(getPositionSize(), getPositionRate()) - - function getPositionSize() { - let balance - if (bot.sessionAndMarketBaseAssetsAreEqual) { - balance = tradingEngine.current.balance.baseAsset.value - } else { - balance = tradingEngine.current.balance.quotedAsset.value - } - const DEFAULT_VALUE = balance - let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value] - - if (strategy.openStage === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition.positionSize === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition.positionSize.formula === undefined) return DEFAULT_VALUE - - let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionSize.formula.id) - if (value === undefined) return DEFAULT_VALUE - return value - } - - function getPositionRate() { - const DEFAULT_VALUE = tradingEngine.current.candle.close.value - let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value] - - if (strategy.openStage === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition.positionRate === undefined) return DEFAULT_VALUE - if (strategy.openStage.initialDefinition.positionRate.formula === undefined) return DEFAULT_VALUE - - let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionRate.formula.id) - if (value === undefined) return DEFAULT_VALUE - return value - } - } } function manageStage() { @@ -1003,14 +955,13 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM evalConditions(stageNode, 'Close Execution') evalFormulas(stageNode, 'Close Execution') - let stageLimitSize = tradingEngine.current.balance.quotedAsset.value / tradingEngine.current.candle.close.value await tradingExecutionModule.checkExecution( executionNode, false, false, - stageLimitSize, - tradingEngine.current.position.closeStageOrdersSize, - tradingEngine.current.position.closeStageFilledSize + tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled, // Stage Size Limit + tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizeFilled, // Stage Size Limit + tradingEngine.current.position.strategyCloseStage ) /* Check the Close Stage Event */