Entry Exit Target Size and Rate implementation
This commit is contained in:
1 parent
269524a358
commit
f5a1d6339b
5 files changed
+266
-182
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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.'
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in new issue
Block a user