Entry Exit Target Size and Rate implementation

This commit is contained in:
Luis Fernando Molina committed 2020-08-05 20:31:06 +02:00
1 parent 269524a358
commit f5a1d6339b
5 files changed
+266 -182

No files matched your search

+26 -42
View File
@@ -80,7 +80,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
let tradingSystemOrder = orders[i]
/* Trading System Validations */
if (tradingSystemOrder.config.positionSizePercentage === undefined) { badDefinitionUnhandledException(undefined, 'tradingSystemOrder.config.positionSizePercentage === undefined', tradingSystemOrder) }
if (tradingSystemOrder.config.percentageOfAlgorithmSize === undefined) { badDefinitionUnhandledException(undefined, 'tradingSystemOrder.config.percentageOfAlgorithmSize === undefined', tradingSystemOrder) }
if (tradingSystemOrder.referenceParent === undefined) { badDefinitionUnhandledException(undefined, 'tradingSystemOrder.referenceParent === undefined', tradingSystemOrder) }
let tradingEngineOrder = tradingEngineModule.getNodeById(tradingSystemOrder.referenceParent.id)
@@ -204,11 +204,13 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
tradingEngineOrder.situationName.value = situationName
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)
/* By default this is the order rate and it is the rate that applies to Market Orders */
tradingEngineOrder.rate.value = tradingEngine.current.candle.close.value
/* Optional Rate Definition */
if (tradingSystemOrder.orderRate !== undefined) {
if (tradingSystemOrder.orderRate.formula !== undefined) {
tradingEngineOrder.rate.value = tradingSystem.formulas.get(tradingSystemOrder.orderRate.formula.id)
if (tradingEngineOrder.rate.value === undefined) { badDefinitionUnhandledException(undefined, 'tradingEngineOrder.rate.value === undefined', tradingEngineOrder) }
if (isNaN(tradingEngineOrder.rate.value) === true) { badDefinitionUnhandledException(undefined, 'isNaN(tradingEngineOrder.rate.value) === true', tradingEngineOrder) }
@@ -220,45 +222,24 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
}
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) { badDefinitionUnhandledException(undefined, 'executionAlgorithm.sizeInBaseAsset === undefined', executionAlgorithm) }
if (executionAlgorithm.sizeInBaseAsset.formula === undefined) { badDefinitionUnhandledException(undefined, 'executionAlgorithm.sizeInBaseAsset.formula === undefined', executionAlgorithm.sizeInBaseAsset) }
sizeFormula = executionAlgorithm.sizeInBaseAsset.formula
} else {
/* Position was defined in Quoted Asset */
if (executionAlgorithm.sizeInQuotedAsset === undefined) { badDefinitionUnhandledException(undefined, 'executionAlgorithm.sizeInQuotedAsset === undefined', executionAlgorithm) }
if (executionAlgorithm.sizeInQuotedAsset.formula === undefined) { badDefinitionUnhandledException(undefined, 'executionAlgorithm.sizeInQuotedAsset.formula === undefined', executionAlgorithm.sizeInBaseAsset) }
sizeFormula = executionAlgorithm.sizeInQuotedAsset.formula
}
/* Validate that this config exists */
if (executionAlgorithm.config.percentageOfStageTargetSize === undefined) { badDefinitionUnhandledException(undefined, 'executionAlgorithm.config.percentageOfStageTargetSize === undefined', executionAlgorithm) }
if (isNaN(executionAlgorithm.config.percentageOfStageTargetSize) === true) { badDefinitionUnhandledException(undefined, 'isNaN(executionAlgorithm.config.percentageOfStageTargetSize) === true', executionAlgorithm) }
/* Order Size Calculation */
let algorithmSize = tradingSystem.formulas.get(sizeFormula.id)
if (algorithmSize === undefined) { badDefinitionUnhandledException(undefined, 'algorithmSize === undefined', sizeFormula) }
if (isNaN(algorithmSize) === true) { badDefinitionUnhandledException(undefined, 'isNaN(algorithmSize) === true', sizeFormula) }
let algorithmSizeInBaseAsset = tradingEngineStage.stageBaseAsset.targetSize.value * executionAlgorithm.config.percentageOfStageTargetSize / 100
let algorithmSizeInQuotedAsset = tradingEngineStage.stageQuotedAsset.targetSize.value * executionAlgorithm.config.percentageOfStageTargetSize / 100
/* Validate that this config exists */
if (tradingSystemOrder.config.positionSizePercentage === undefined) { badDefinitionUnhandledException(undefined, 'tradingSystemOrder.config.positionSizePercentage === undefined', executionAlgorithm) }
if (tradingSystemOrder.config.percentageOfAlgorithmSize === undefined) { badDefinitionUnhandledException(undefined, 'tradingSystemOrder.config.percentageOfAlgorithmSize === undefined', tradingSystemOrder) }
if (isNaN(tradingSystemOrder.config.percentageOfAlgorithmSize) === true) { badDefinitionUnhandledException(undefined, 'isNaN(tradingSystemOrder.config.percentageOfAlgorithmSize) === true', tradingSystemOrder) }
if (tradingEngine.current.position.positionBaseAsset.size.value > 0) {
/* Position was defined in Base Asset */
tradingEngineOrder.orderBaseAsset.size.value = algorithmSize * tradingSystemOrder.config.positionSizePercentage / 100
tradingEngineOrder.orderQuotedAsset.size.value = tradingEngineOrder.orderBaseAsset.size.value * tradingEngineOrder.rate.value
} else {
/* Position was defined in Quoted Asset */
tradingEngineOrder.orderQuotedAsset.size.value = algorithmSize * tradingSystemOrder.config.positionSizePercentage / 100
tradingEngineOrder.orderBaseAsset.size.value = tradingEngineOrder.orderQuotedAsset.size.value / tradingEngineOrder.rate.value
}
tradingEngineOrder.orderBaseAsset.size.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.size.value, 10)
tradingEngineOrder.orderBaseAsset.size.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.size.value, 10)
/* Size in Base Asset */
tradingEngineOrder.orderBaseAsset.size.value = algorithmSizeInBaseAsset * tradingSystemOrder.config.percentageOfAlgorithmSize / 100
/* Check against the Stage Size Limit */
/* Size in Quoted Asset */
tradingEngineOrder.orderQuotedAsset.size.value = algorithmSizeInQuotedAsset * tradingSystemOrder.config.percentageOfAlgorithmSize / 100
/* Check that the Size calculated would not surpass Stage Target Size */
if (
tradingEngineOrder.orderBaseAsset.size.value + tradingEngineStage.stageBaseAsset.sizePlaced.value >
tradingEngineStage.stageBaseAsset.targetSize.value
@@ -271,6 +252,9 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
) {
tradingEngineOrder.orderQuotedAsset.size.value = tradingEngineStage.stageQuotedAsset.targetSize.value - tradingEngineStage.stageQuotedAsset.sizePlaced.value
}
tradingEngineOrder.orderBaseAsset.size.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.size.value, 10)
tradingEngineOrder.orderQuotedAsset.size.value = global.PRECISE(tradingEngineOrder.orderQuotedAsset.size.value, 10)
}
async function createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) {
@@ -481,11 +465,11 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
function sizeFilledSimulation() {
/* Size Filled */
tradingEngineOrder.orderBaseAsset.sizeFilled.value =
tradingEngineOrder.orderBaseAsset.size.value *
(tradingEngineOrder.orderBaseAsset.size.value - tradingEngineOrder.orderBaseAsset.feesPaid.value) *
tradingEngineOrder.orderStatistics.percentageFilled.value / 100
tradingEngineOrder.orderQuotedAsset.sizeFilled.value =
tradingEngineOrder.orderQuotedAsset.size.value *
(tradingEngineOrder.orderQuotedAsset.size.value - tradingEngineOrder.orderQuotedAsset.feesPaid.value) *
tradingEngineOrder.orderStatistics.percentageFilled.value / 100
tradingEngineOrder.orderBaseAsset.sizeFilled.value = global.PRECISE(tradingEngineOrder.orderBaseAsset.sizeFilled.value, 10)
+118 -76
View File
@@ -11,7 +11,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
applyTakeProfitFormula: applyTakeProfitFormula,
updateStopLoss: updateStopLoss,
updateTakeProfit: updateTakeProfit,
initializePositionSizeAndRate: initializePositionSizeAndRate,
initialTargets: initialTargets,
updateEnds: updateEnds,
updateStatus: updateStatus,
updateCounters: updateCounters,
@@ -100,93 +100,122 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
tradingEngine.current.position.takeProfit.takeProfitStage.value = stage
}
function initializePositionSizeAndRate() {
function initialTargets(stageNode) {
setPositionSize()
setPositionRate()
if (stageNode.initialTargets === undefined) {
const message = 'Stage without Initial Targets node. Add one please.'
badDefinitionUnhandledException(undefined, message, stageNode)
}
tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value
setTargetRate()
setTargetSize()
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)
function setTargetRate() {
if (stageNode.initialTargets.targetRate === undefined) {
const message = 'Target Rate Node not Found. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets)
}
if (stageNode.initialTargets.targetRate.formula === undefined) {
const message = 'Formula of Target Rate Node not Found. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetRate)
}
/* 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)
let value = tradingSystem.formulas.get(stageNode.initialTargets.targetRate.formula.id)
if (value === undefined) {
const message = 'Target Rate can not be undefined. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetRate.formula)
}
if (isNaN(value)) {
const message = 'Target Rate must be a number. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetRate.formula)
}
switch (stageNode.type) {
case 'Open Stage': {
tradingEngine.current.position.entryTargetRate.value = global.PRECISE(value, 10)
break
}
}
/* 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)
case 'Close Stage': {
tradingEngine.current.position.exitTargetRate.value = global.PRECISE(value, 10)
break
}
}
}
function setPositionRate() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
if (strategy.openStage.initialDefinition.positionRate === undefined) {
const errorText = 'Position Rate Node not Found. Fix this please.'
tradingSystem.errors.push([strategy.openStage.initialDefinition.id, errorText])
throw (errorText)
}
if (strategy.openStage.initialDefinition.positionRate.formula === undefined) {
const errorText = 'Formula of Position Rate Node not Found. Fix this please.'
tradingSystem.errors.push([strategy.openStage.initialDefinition.positionRate.id, errorText])
throw (errorText)
function setTargetSize() {
/* Basic Validation */
if (
stageNode.initialTargets.targetSizeInBaseAsset !== undefined &&
stageNode.initialTargets.targetSizeInQuotedAsset !== undefined
) {
const message = 'Only Target Size In Base Asset or Target Size In Quoted Asset is allowed. Remove one of them please.'
badDefinitionUnhandledException(undefined, message, stageNode)
}
let value = tradingSystem.formulas.get(strategy.openStage.initialDefinition.positionRate.formula.id)
if (value === undefined) {
const errorText = 'Position Rate can not be undefined. Fix this please.'
tradingSystem.errors.push([strategy.openStage.initialDefinition.positionRate.formula.id, errorText])
throw (errorText)
/* Position In Base Asset */
if (stageNode.initialTargets.targetSizeInBaseAsset !== undefined) {
if (stageNode.initialTargets.targetSizeInBaseAsset.formula !== undefined) {
let value = tradingSystem.formulas.get(stageNode.initialTargets.targetSizeInBaseAsset.formula.id)
if (value === undefined) {
const message = 'Target Size In Base Asset cannot be undefined. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInBaseAsset.formula)
}
if (value === undefined) {
const message = 'Target Size In Base Asset cannot be zero. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInBaseAsset.formula)
}
switch (stageNode.type) {
case 'Open Stage': {
tradingEngine.current.position.positionBaseAsset.entryTargetSize.value = global.PRECISE(value, 10)
tradingEngine.current.position.positionQuotedAsset.entryTargetSize.value =
global.PRECISE(value * tradingEngine.current.position.entryTargetRate.value, 10)
break
}
case 'Close Stage': {
tradingEngine.current.position.positionBaseAsset.exitTargetSize.value = global.PRECISE(value, 10)
tradingEngine.current.position.positionQuotedAsset.exitTargetSize.value =
global.PRECISE(value * tradingEngine.current.position.exitTargetRate.value, 10)
break
}
}
} else {
const message = 'You need to specify a Formula for this.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInBaseAsset)
}
}
tradingEngine.current.position.rate.value = value
/* Position In Quoted Asset */
if (stageNode.initialTargets.targetSizeInQuotedAsset !== undefined) {
if (stageNode.initialTargets.targetSizeInQuotedAsset.formula !== undefined) {
let value = tradingSystem.formulas.get(stageNode.initialTargets.targetSizeInQuotedAsset.formula.id)
if (value === undefined) {
const message = 'Target Size In Quoted Asset cannot be undefined. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInQuotedAsset.formula)
}
if (value === undefined) {
const message = 'Target Size In Quoted Asset cannot be zero. Fix this please.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInQuotedAsset.formula)
}
switch (stageNode.type) {
case 'Open Stage': {
tradingEngine.current.position.positionQuotedAsset.entryTargetSize.value = global.PRECISE(value, 10)
tradingEngine.current.position.positionBaseAsset.entryTargetSize.value =
global.PRECISE(value / tradingEngine.current.position.entryTargetRate.value, 10)
break
}
case 'Close Stage': {
tradingEngine.current.position.positionQuotedAsset.exitTargetSize.value = global.PRECISE(value, 10)
tradingEngine.current.position.positionBaseAsset.exitTargetSize.value =
global.PRECISE(value / tradingEngine.current.position.exitTargetRate.value, 10)
break
}
}
} else {
const errorText = 'You need to specify a Formula for this.'
badDefinitionUnhandledException(undefined, message, stageNode.initialTargets.targetSizeInQuotedAsset.formula)
}
}
}
}
@@ -233,11 +262,11 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
/* ROI Calculation */
tradingEngine.current.position.positionBaseAsset.ROI.value =
tradingEngine.current.position.positionBaseAsset.profitLoss.value * 100 /
tradingEngine.current.position.positionBaseAsset.size.value
tradingEngine.current.position.positionBaseAsset.entryTargetSize.value
tradingEngine.current.position.positionQuotedAsset.ROI.value =
tradingEngine.current.position.positionQuotedAsset.profitLoss.value * 100 /
tradingEngine.current.position.positionQuotedAsset.size.value
tradingEngine.current.position.positionQuotedAsset.entryTargetSize.value
tradingEngine.current.position.positionBaseAsset.ROI.value = global.PRECISE(tradingEngine.current.position.positionBaseAsset.ROI.value, 10)
@@ -253,4 +282,17 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
tradingEngine.current.position.positionQuotedAsset.hitFail.value = 'FAIL'
}
}
function badDefinitionUnhandledException(err, message, node) {
tradingSystem.errors.push([node.id, message])
logger.write(MODULE_NAME, "[ERROR] -> " + message);
logger.write(MODULE_NAME, "[ERROR] -> node.name = " + node.name);
logger.write(MODULE_NAME, "[ERROR] -> node.type = " + node.type);
logger.write(MODULE_NAME, "[ERROR] -> node.config = " + JSON.stringify(node.config));
if (err !== undefined) {
logger.write(MODULE_NAME, "[ERROR] -> err.stack = " + err.stack);
}
throw 'It is not safe to continue with a Definition Error like this. Please fix the problem and try again.'
}
}
+105 -55
View File
@@ -343,9 +343,10 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
tradingEngine.previous.balance.baseAsset.value = tradingEngine.current.balance.baseAsset.value
tradingEngine.previous.balance.quotedAsset.value = tradingEngine.current.balance.quotedAsset.value
/* Position size and rate */
tradingPositionModule.initializePositionSizeAndRate()
initializeOpenStageSizeTarget()
/* Entry Position size and rate */
tradingSystem.evalFormulas(stageNode, 'Initial Targets')
tradingPositionModule.initialTargets(stageNode)
initializeStageTargetSize()
/* Check Execution at open stage node */
tradingSystem.evalConditions(stageNode, 'Open Execution')
@@ -381,16 +382,36 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
tradingEngine.current.strategyOpenStage
)
/*
The Open is finished when the fillSize + feesPaid reaches the Position Size.
This can happens at any time when we update the sizeFilled value when we see
at the exchange that orders were filled.
The Open is finished when the placedSize reaches the targetSize in any of the
stage assets, and the fillSize + feesPaid reaches the placedSize also in any
of the stage Assets.
This can happens at any time when we update the sizeFilled and the feesPaid values
when we see at the exchange that orders were filled.
*/
if (
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageBaseAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value * 0.999) {
(
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize
||
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizePlaced >=
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize
)
&&
(
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageBaseAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value
||
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageQuotedAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizePlaced.value
)
) {
changeStageStatus('Open Stage', 'Closed', 'Position Size Filled')
initializeCloseStageSizeTarget()
} else {
/* Check the Close Stage Event */
tradingSystem.evalConditions(stageNode, 'Close Stage Event')
@@ -409,63 +430,51 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
let stageNode = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value].openStage
let executionNode = stageNode.openExecution
/* Check if there are unfilled orders */
if (
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageBaseAsset.feesPaid.value <
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value * 0.999) {
/* There are unfilled orders, we will check if they were executed, and cancel the ones that were not. */
/*
Check if there are unfilled orders, we will check if they were executed,
and cancel the ones that were not.
*/
tradingSystem.evalConditions(stageNode, 'Open Execution')
tradingSystem.evalFormulas(stageNode, 'Open Execution')
tradingSystem.evalConditions(stageNode, 'Open Execution')
tradingSystem.evalFormulas(stageNode, 'Open Execution')
await tradingExecutionModule.runExecution(
executionNode,
true,
tradingEngine.current.strategyOpenStage
)
}
await tradingExecutionModule.runExecution(
executionNode,
true,
tradingEngine.current.strategyOpenStage
)
/*
The Closing is finished when the fillSize + feesPaid reaches the ordersSize.
This can happens either because we update the sizeFilled value when we see
at the exchange that orders were filled, or we reduce the ordersSize when
we cancel not yet filled orders.
we cancel not yet filled orders. Here it does not matter the targetSize since
this status represent a force closure of this stage.
*/
if (
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageBaseAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value * 0.999) {
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value
||
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageQuotedAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizePlaced.value
) {
changeStageStatus('Open Stage', 'Closed')
initializeCloseStageSizeTarget()
}
}
function initializeOpenStageSizeTarget() {
function initializeStageTargetSize() {
/*
Here we will transform the position size into targets for each asset of the stage.
*/
if (tradingEngine.current.position.positionBaseAsset.size.value > 0) {
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value = tradingEngine.current.position.positionBaseAsset.size.value
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value =
tradingEngine.current.position.positionBaseAsset.size.value * tradingEngine.current.position.rate.value
} else {
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value = tradingEngine.current.position.positionQuotedAsset.size.value
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value =
tradingEngine.current.position.positionQuotedAsset.size.value / tradingEngine.current.position.rate.value
}
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value = tradingEngine.current.position.positionBaseAsset.entryTargetSize.value
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value = tradingEngine.current.position.positionQuotedAsset.entryTargetSize.value
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value = global.PRECISE(tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value, 10)
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value = global.PRECISE(tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value, 10)
}
function initializeCloseStageSizeTarget() {
/*
Here we will move the size filled of the open stage to the size target of the close stage.
*/
tradingEngine.current.strategyCloseStage.stageBaseAsset.targetSize.value = tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value
tradingEngine.current.strategyCloseStage.stageQuotedAsset.targetSize.value = tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizeFilled.value
}
}
function runManageStage() {
@@ -876,6 +885,12 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
the total filled size of the Open Stage. By skiping execution now
we allow the open stage to get a final value for sizeFilled that we can use.
*/
/* Exit Position size and rate */
tradingSystem.evalFormulas(stageNode, 'Initial Targets')
tradingPositionModule.initialTargets(stageNode)
initializeStageTargetSize()
changeStageStatus('Close Stage', 'Open')
return
}
@@ -898,14 +913,35 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
)
/*
The Close Stage is finished when the fillSize + feesPaid reaches the Open Fill Size.
This can happens at any time when we update the sizeFilled value when we see
at the exchange that orders were filled.
The Open is finished when the placedSize reaches the targetSize in any of the
stage assets, and the fillSize + feesPaid reaches the placedSize also in any
of the stage Assets.
This can happens at any time when we update the sizeFilled and the feesPaid values
when we see at the exchange that orders were filled.
*/
if (
tradingEngine.current.strategyCloseStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyCloseStage.stageBaseAsset.feesPaid.value >=
tradingEngine.current.strategyCloseStage.stageBaseAsset.sizePlaced.value * 0.999) {
(
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize
||
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizePlaced >=
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize
)
&&
(
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageBaseAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageBaseAsset.sizePlaced.value
||
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizeFilled.value +
tradingEngine.current.strategyOpenStage.stageQuotedAsset.feesPaid.value >=
tradingEngine.current.strategyOpenStage.stageQuotedAsset.sizePlaced.value
)
) {
changeStageStatus('Close Stage', 'Closed', 'Size Placed Filled')
} else {
/* Check the Close Stage Event */
@@ -942,6 +978,17 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
exitPositionAndStrategy()
}
function initializeStageTargetSize() {
/*
Here we will transform the position size into targets for each asset of the stage.
*/
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value = tradingEngine.current.position.positionBaseAsset.exitTargetSize.value
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value = tradingEngine.current.position.positionQuotedAsset.exitTargetSize.value
tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value = global.PRECISE(tradingEngine.current.strategyOpenStage.stageBaseAsset.targetSize.value, 10)
tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value = global.PRECISE(tradingEngine.current.strategyOpenStage.stageQuotedAsset.targetSize.value, 10)
}
function exitPositionAndStrategy() {
/* Position Statistics & Results */
@@ -1187,15 +1234,18 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
function updateStatus() {
if (tradingEngine.current.strategyTriggerStage.status.value === 'Closed') {
resetStage(tradingEngine.current.strategyTriggerStage)
resetStage(tradingEngine.current.strategyTriggerStage.status)
}
if (tradingEngine.current.strategyOpenStage.status.value === 'Closed') {
resetStage(tradingEngine.current.strategyOpenStage)
resetStage(tradingEngine.current.strategyOpenStage.status)
}
if (tradingEngine.current.strategyManageStage.status.value === 'Closed') {
resetStage(tradingEngine.current.strategyManageStage)
resetStage(tradingEngine.current.strategyManageStage.status)
}
if (tradingEngine.current.strategyCloseStage.status.value === 'Closed') {
resetStage(tradingEngine.current.strategyTriggerStage)
resetStage(tradingEngine.current.strategyOpenStage)
resetStage(tradingEngine.current.strategyManageStage)
resetStage(tradingEngine.current.strategyCloseStage)
}
}
+16 -8
View File
@@ -118,17 +118,25 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM
}
async function run() {
/* Run the Trigger Stage */
tradingStagesModule.runTriggerStage()
try {
/* Run the Trigger Stage */
tradingStagesModule.runTriggerStage()
/* Run the Open Stage */
await tradingStagesModule.runOpenStage()
/* Run the Open Stage */
await tradingStagesModule.runOpenStage()
/* Run the Manage Stage */
tradingStagesModule.runManageStage()
/* Run the Manage Stage */
tradingStagesModule.runManageStage()
/* Run the Close Stage */
await tradingStagesModule.runCloseStage()
/* Run the Close Stage */
await tradingStagesModule.runCloseStage()
} catch (err) {
/*
If an error ocurred during execution, it was alreeady logged and
included at the errors array. That means we need to do nothing here,
just prevent the execution to be halted for not handling exceptions.
*/
}
}
function evalNode(node, evaluating, descendentOfNodeType, isDescendent) {
+1 -1
View File
@@ -41,7 +41,7 @@ global.UNIQUE_ID = function () {
}
global.PRECISE = function (floatNumber, precision) {
return parseFloat(Number.parseFloat(floatNumber).toPrecision(precision))
return this.parseFloat(floatNumber.toFixed(precision))
}
process.on('uncaughtException', function (err) {