STOP TP fixes

This commit is contained in:
Luis Fernando Molina committed 2020-10-22 13:09:31 +02:00
1 parent b7811b2914
commit e0f683aec3
10 files changed
+406 -316

No files matched your search

@@ -50,6 +50,10 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
or the task / session was restarted.
*/
if (bot.FIRST_EXECUTION === true) {
/* Starting begin and end */
tradingEngine.current.episode.begin.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.episode.end.value = tradingEngine.current.episode.candle.end.value
/* Getting the begin Balance from the session configuration */
tradingEngine.current.episode.episodeBaseAsset.beginBalance.value = sessionParameters.sessionBaseAsset.config.initialBalance
tradingEngine.current.episode.episodeQuotedAsset.beginBalance.value = sessionParameters.sessionQuotedAsset.config.initialBalance
@@ -62,7 +66,6 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
tradingEngine.current.episode.status.value = 'Open'
tradingEngine.current.episode.serialNumber.value = 1
tradingEngine.current.episode.identifier.value = global.UNIQUE_ID()
tradingEngine.current.episode.begin.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.episode.beginRate.value = tradingEngine.current.episode.candle.close.value
}
}
@@ -73,7 +76,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
function closeEpisode() {
tradingEngine.current.episode.status.value = 'Closed'
tradingEngine.current.episode.end.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.episode.end.value = tradingEngine.current.episode.candle.end.value
tradingEngine.current.episode.endRate.value = tradingEngine.current.episode.candle.close.value
tradingEngine.current.episode.episodeBaseAsset.endBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value
tradingEngine.current.episode.episodeQuotedAsset.endBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value
@@ -85,7 +88,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
function updateEnds() {
if (tradingEngine.current.episode.status.value === 'Open') {
tradingEngine.current.episode.end.value = tradingEngine.current.episode.candle.end.value
tradingEngine.current.episode.end.value = tradingEngine.current.episode.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.episode.endRate.value = tradingEngine.current.episode.candle.close.value
tradingEngine.current.episode.episodeBaseAsset.endBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value
tradingEngine.current.episode.episodeQuotedAsset.endBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value
@@ -160,7 +163,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
tradingEngine.current.episode.episodeBaseAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.hitRatio.value, 10)
tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value, 10)
}
/*
Updating Annualized Rate Of Return
@@ -51,11 +51,14 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
function openPosition(situationName) {
/* Starting begin and end */
tradingEngine.current.position.begin.value = tradingEngine.current.episode.cycle.lastBegin.value
tradingEngine.current.position.end.value = tradingEngine.current.episode.cycle.lastEnd.value
/* Recording the opening at the Trading Engine Data Structure */
tradingEngine.current.position.status.value = 'Open'
tradingEngine.current.position.serialNumber.value = tradingEngine.current.episode.episodeCounters.positions.value + 1
tradingEngine.current.position.identifier.value = global.UNIQUE_ID()
tradingEngine.current.position.begin.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.position.beginRate.value = tradingEngine.current.episode.candle.close.value
tradingEngine.current.position.positionBaseAsset.beginBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value
tradingEngine.current.position.positionQuotedAsset.beginBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value
@@ -79,11 +82,20 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
function closingPosition(exitType) {
tradingEngine.current.position.status.value = 'Closing'
tradingEngine.current.position.exitType.value = exitType
/*
By the time we figured out that the stop loss or take profit were hit, or
for whatever reason the position needs to be closed, the take profit and
stop loss values for the next candle have already been calculated. In order
to avoid being plotted, we will put them in zero.
*/
tradingEngine.current.position.stopLoss.value = 0
tradingEngine.current.position.takeProfit.value = 0
}
function closePosition() {
tradingEngine.current.position.status.value = 'Closed'
tradingEngine.current.position.end.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.position.end.value = tradingEngine.current.episode.cycle.lastEnd.value
tradingEngine.current.position.endRate.value = tradingEngine.current.episode.candle.close.value
tradingEngine.current.position.positionBaseAsset.endBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value
tradingEngine.current.position.positionQuotedAsset.endBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value
@@ -94,17 +106,17 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
tradingEngineModule.cloneValues(tradingEngine.current.position, tradingEngine.last.position)
cycleBasedStatistics()
/* Updating Hits & Fails */
if (tradingEngine.current.position.positionBaseAsset.profitLoss.value > 0) {
tradingEngine.current.episode.episodeBaseAsset.hits.value++
}
}
if (tradingEngine.current.position.positionBaseAsset.profitLoss.value < 0) {
tradingEngine.current.episode.episodeBaseAsset.fails.value++
}
if (tradingEngine.current.position.positionQuotedAsset.profitLoss.value > 0) {
tradingEngine.current.episode.episodeQuotedAsset.hits.value++
}
}
if (tradingEngine.current.position.positionQuotedAsset.profitLoss.value < 0) {
tradingEngine.current.episode.episodeQuotedAsset.fails.value++
}
@@ -112,10 +124,27 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
function applyStopLossFormula(formulas, formulaId) {
tradingEngine.current.position.stopLoss.value = formulas.get(formulaId)
updateStopLossTakeProfitBeginEnd(tradingEngine.current.position.stopLoss)
}
function applyTakeProfitFormula(formulas, formulaId) {
tradingEngine.current.position.takeProfit.value = formulas.get(formulaId)
updateStopLossTakeProfitBeginEnd(tradingEngine.current.position.takeProfit)
}
function updateStopLossTakeProfitBeginEnd(node) {
/*
Both the Stop Loss and the Take Profit have their own Begin and End.
Ther reason for this is because they represent targets to be checked
at the next candle, so it does not apply that they share the begin and
end of the position itself.
*/
node.begin.value =
tradingEngine.current.episode.candle.begin.value +
sessionParameters.timeFrame.config.value
node.end.value =
tradingEngine.current.episode.candle.end.value +
sessionParameters.timeFrame.config.value
}
function updateStopLoss(phase) {
@@ -253,7 +282,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
function updateEnds() {
if (tradingEngine.current.position.status.value === 'Open') {
tradingEngine.current.position.end.value = tradingEngine.current.episode.candle.end.value
tradingEngine.current.position.end.value = tradingEngine.current.position.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.position.endRate.value = tradingEngine.current.episode.candle.close.value
tradingEngine.current.position.positionBaseAsset.endBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value
tradingEngine.current.position.positionQuotedAsset.endBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value
@@ -305,7 +334,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
/* Hit Fail Calculation */
if (tradingEngine.current.position.positionBaseAsset.ROI.value > 0) {
tradingEngine.current.position.positionBaseAsset.hitFail.value = 'Hit'
}
}
if (tradingEngine.current.position.positionBaseAsset.ROI.value < 0) {
tradingEngine.current.position.positionBaseAsset.hitFail.value = 'Fail'
}
@@ -314,7 +343,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
}
if (tradingEngine.current.position.positionQuotedAsset.ROI.value > 0) {
tradingEngine.current.position.positionQuotedAsset.hitFail.value = 'Hit'
}
}
if (tradingEngine.current.position.positionQuotedAsset.ROI.value < 0) {
tradingEngine.current.position.positionQuotedAsset.hitFail.value = 'Fail'
}
@@ -348,7 +377,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
/* Hit Fail Calculation */
if (tradingEngine.current.position.positionStatistics.ROI.value > 0) {
tradingEngine.current.position.positionStatistics.hitFail.value = 'Hit'
}
}
if (tradingEngine.current.position.positionStatistics.ROI.value < 0) {
tradingEngine.current.position.positionStatistics.hitFail.value = 'Fail'
}
+308 -291
View File
@@ -393,6 +393,8 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
function runManageStage() {
if (tradingEngine.current.episode.cycle.value !== 'First') { return }
runWhenStatusIsOpening()
runWhenStatusIsOpen()
@@ -428,331 +430,331 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
/* Checking if Stop or Take Profit were hit */
checkStopLossOrTakeProfitWasHit()
}
}
function calculateStopLoss() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let phase
if (manageStage !== undefined) {
if (manageStage.managedStopLoss !== undefined) {
phase = manageStage.managedStopLoss.phases[tradingEngine.current.position.stopLoss.stopLossPhase.value - 1]
}
}
if (phase !== undefined) {
if (phase.formula !== undefined) {
let previousValue = tradingEngine.current.position.stopLoss.value
tradingPositionModule.applyStopLossFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.current.position.stopLoss.value !== previousValue) {
announcementsModule.makeAnnoucements(phase)
function calculateStopLoss() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let phase
if (manageStage !== undefined) {
if (manageStage.managedStopLoss !== undefined) {
phase = manageStage.managedStopLoss.phases[tradingEngine.current.position.stopLoss.stopLossPhase.value - 1]
}
}
}
}
function calculateTakeProfit() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let phase
if (manageStage !== undefined) {
if (manageStage.managedTakeProfit !== undefined) {
phase = manageStage.managedTakeProfit.phases[tradingEngine.current.position.takeProfit.takeProfitPhase.value - 1]
}
}
if (phase !== undefined) {
if (phase.formula !== undefined) {
let previousValue = tradingEngine.current.position.takeProfit.value
tradingPositionModule.applyTakeProfitFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.current.position.takeProfit.value !== previousValue) {
announcementsModule.makeAnnoucements(phase)
}
}
}
}
function calculateStopLossPosition() {
/*
The position of the Stop Loss (above or below the price) is needed in order to know
later if the price hit the Stop Loss or not at every Simulation candle. When we get
the first values of the simulation of the Stop Loss we check if it is above or below
the Position Rate, and we assign the values Above or Below to it.
*/
if (tradingEngine.current.position.stopLoss.stopLossPosition.value === tradingEngine.current.position.stopLoss.stopLossPosition.config.initialValue) {
if (tradingEngine.current.position.stopLoss.value > tradingEngine.current.position.entryTargetRate.value) {
tradingEngine.current.position.stopLoss.stopLossPosition.value = 'Above'
} else {
tradingEngine.current.position.stopLoss.stopLossPosition.value = 'Below'
}
}
}
function calculateTakeProfitPosition() {
/*
The position of the Take Profit (above or below the price) is needed in order to know
later if the price hit the Take Profit or not at every Simulation candle. When we get
the first values of the simulation of the Take Profits we check if it is above or below
the Position Rates, and we assign the values Above or Below to it.
*/
if (tradingEngine.current.position.takeProfit.takeProfitPosition.value === tradingEngine.current.position.takeProfit.takeProfitPosition.config.initialValue) {
if (tradingEngine.current.position.takeProfit.value > tradingEngine.current.position.entryTargetRate.value) {
tradingEngine.current.position.takeProfit.takeProfitPosition.value = 'Above'
} else {
tradingEngine.current.position.takeProfit.takeProfitPosition.value = 'Below'
}
}
}
function checkStopPhasesEvents() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let parentNode
let phaseIndex
let phase
let stopLoss
if (manageStage !== undefined) {
if (manageStage.managedStopLoss !== undefined) {
parentNode = manageStage
phaseIndex = tradingEngine.current.position.stopLoss.stopLossPhase.value - 1
stopLoss = manageStage.managedStopLoss
phase = stopLoss.phases[phaseIndex]
}
}
if (parentNode !== undefined) {
if (phase === undefined) { return } // trying to jump to a phase that does not exists.
/* Check the next Phase Event. */
let nextPhaseEvent = phase.nextPhaseEvent
if (nextPhaseEvent !== undefined) {
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
let situation = nextPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(nextPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(stopLoss.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
tradingPositionModule.updateStopLoss(tradingEngine.current.position.stopLoss.stopLossPhase.value + 1)
announcementsModule.makeAnnoucements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.nextPhase.value = 1
return // only one event can pass at the time
if (phase !== undefined) {
if (phase.formula !== undefined) {
let previousValue = tradingEngine.current.position.stopLoss.value
tradingPositionModule.applyStopLossFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.current.position.stopLoss.value !== previousValue) {
announcementsModule.makeAnnoucements(phase)
}
}
}
/* Check the Move to Phase Events. */
for (let n = 0; n < phase.moveToPhaseEvents.length; n++) {
let moveToPhaseEvent = phase.moveToPhaseEvents[n]
if (moveToPhaseEvent !== undefined) {
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
let situation = moveToPhaseEvent.situations[k]
}
function calculateTakeProfit() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let phase
if (manageStage !== undefined) {
if (manageStage.managedTakeProfit !== undefined) {
phase = manageStage.managedTakeProfit.phases[tradingEngine.current.position.takeProfit.takeProfitPhase.value - 1]
}
}
if (phase !== undefined) {
if (phase.formula !== undefined) {
let previousValue = tradingEngine.current.position.takeProfit.value
tradingPositionModule.applyTakeProfitFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.current.position.takeProfit.value !== previousValue) {
announcementsModule.makeAnnoucements(phase)
}
}
}
}
function calculateStopLossPosition() {
/*
The position of the Stop Loss (above or below the price) is needed in order to know
later if the price hit the Stop Loss or not at every Simulation candle. When we get
the first values of the simulation of the Stop Loss we check if it is above or below
the Position Rate, and we assign the values Above or Below to it.
*/
if (tradingEngine.current.position.stopLoss.stopLossPosition.value === tradingEngine.current.position.stopLoss.stopLossPosition.config.initialValue) {
if (tradingEngine.current.position.stopLoss.value > tradingEngine.current.position.entryTargetRate.value) {
tradingEngine.current.position.stopLoss.stopLossPosition.value = 'Above'
} else {
tradingEngine.current.position.stopLoss.stopLossPosition.value = 'Below'
}
}
}
function calculateTakeProfitPosition() {
/*
The position of the Take Profit (above or below the price) is needed in order to know
later if the price hit the Take Profit or not at every Simulation candle. When we get
the first values of the simulation of the Take Profits we check if it is above or below
the Position Rates, and we assign the values Above or Below to it.
*/
if (tradingEngine.current.position.takeProfit.takeProfitPosition.value === tradingEngine.current.position.takeProfit.takeProfitPosition.config.initialValue) {
if (tradingEngine.current.position.takeProfit.value > tradingEngine.current.position.entryTargetRate.value) {
tradingEngine.current.position.takeProfit.takeProfitPosition.value = 'Above'
} else {
tradingEngine.current.position.takeProfit.takeProfitPosition.value = 'Below'
}
}
}
function checkStopPhasesEvents() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let manageStage = strategy.manageStage
let parentNode
let phaseIndex
let phase
let stopLoss
if (manageStage !== undefined) {
if (manageStage.managedStopLoss !== undefined) {
parentNode = manageStage
phaseIndex = tradingEngine.current.position.stopLoss.stopLossPhase.value - 1
stopLoss = manageStage.managedStopLoss
phase = stopLoss.phases[phaseIndex]
}
}
if (parentNode !== undefined) {
if (phase === undefined) { return } // trying to jump to a phase that does not exists.
/* Check the next Phase Event. */
let nextPhaseEvent = phase.nextPhaseEvent
if (nextPhaseEvent !== undefined) {
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
let situation = nextPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(moveToPhaseEvent.id)
tradingSystem.highlights.push(nextPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(stopLoss.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
let moveToPhase = moveToPhaseEvent.referenceParent
if (moveToPhase !== undefined) {
for (let q = 0; q < stopLoss.phases.length; q++) {
if (stopLoss.phases[q].id === moveToPhase.id) {
tradingPositionModule.updateStopLoss(q + 1)
}
}
} else {
tradingSystem.errors.push([moveToPhaseEvent.id, 'This Node needs to reference a Phase.'])
continue
}
announcementsModule.makeAnnoucements(moveToPhaseEvent)
tradingPositionModule.updateStopLoss(tradingEngine.current.position.stopLoss.stopLossPhase.value + 1)
announcementsModule.makeAnnoucements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.moveToPhase.value = 1
tradingEngine.current.episode.distanceToEvent.nextPhase.value = 1
return // only one event can pass at the time
}
}
}
/* Check the Move to Phase Events. */
for (let n = 0; n < phase.moveToPhaseEvents.length; n++) {
let moveToPhaseEvent = phase.moveToPhaseEvents[n]
if (moveToPhaseEvent !== undefined) {
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
let situation = moveToPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(moveToPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(stopLoss.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
let moveToPhase = moveToPhaseEvent.referenceParent
if (moveToPhase !== undefined) {
for (let q = 0; q < stopLoss.phases.length; q++) {
if (stopLoss.phases[q].id === moveToPhase.id) {
tradingPositionModule.updateStopLoss(q + 1)
}
}
} else {
tradingSystem.errors.push([moveToPhaseEvent.id, 'This Node needs to reference a Phase.'])
continue
}
announcementsModule.makeAnnoucements(moveToPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.moveToPhase.value = 1
return // only one event can pass at the time
}
}
}
}
}
}
}
function checkTakeProfitPhaseEvents() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let openStage = strategy.openStage
let manageStage = strategy.manageStage
let parentNode
let phaseIndex
let phase
let takeProfit
if (manageStage !== undefined) {
if (manageStage.managedTakeProfit !== undefined) {
parentNode = manageStage
phaseIndex = tradingEngine.current.position.takeProfit.takeProfitPhase.value - 1
takeProfit = manageStage.managedTakeProfit
phase = takeProfit.phases[phaseIndex]
}
}
if (parentNode !== undefined) {
if (phase === undefined) { return } // trying to jump to a phase that does not exists.
/* Check the next Phase Event. */
let nextPhaseEvent = phase.nextPhaseEvent
if (nextPhaseEvent !== undefined) {
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
let situation = nextPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(nextPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(takeProfit.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
tradingPositionModule.updateTakeProfit(tradingEngine.current.position.takeProfit.takeProfitPhase.value + 1)
announcementsModule.makeAnnoucements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.nextPhase.value = 1
return // only one event can pass at the time
}
function checkTakeProfitPhaseEvents() {
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
let openStage = strategy.openStage
let manageStage = strategy.manageStage
let parentNode
let phaseIndex
let phase
let takeProfit
if (manageStage !== undefined) {
if (manageStage.managedTakeProfit !== undefined) {
parentNode = manageStage
phaseIndex = tradingEngine.current.position.takeProfit.takeProfitPhase.value - 1
takeProfit = manageStage.managedTakeProfit
phase = takeProfit.phases[phaseIndex]
}
}
/* Check the Move to Phase Events. */
for (let n = 0; n < phase.moveToPhaseEvents.length; n++) {
let moveToPhaseEvent = phase.moveToPhaseEvents[n]
if (moveToPhaseEvent !== undefined) {
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
let situation = moveToPhaseEvent.situations[k]
if (parentNode !== undefined) {
if (phase === undefined) { return } // trying to jump to a phase that does not exists.
/* Check the next Phase Event. */
let nextPhaseEvent = phase.nextPhaseEvent
if (nextPhaseEvent !== undefined) {
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
let situation = nextPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(moveToPhaseEvent.id)
tradingSystem.highlights.push(nextPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(takeProfit.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
let moveToPhase = moveToPhaseEvent.referenceParent
if (moveToPhase !== undefined) {
for (let q = 0; q < takeProfit.phases.length; q++) {
if (takeProfit.phases[q].id === moveToPhase.id) {
tradingPositionModule.updateTakeProfit(q + 1)
}
}
} else {
tradingSystem.errors.push([moveToPhaseEvent.id, 'This Node needs to reference a Phase.'])
continue
}
announcementsModule.makeAnnoucements(moveToPhaseEvent)
tradingPositionModule.updateTakeProfit(tradingEngine.current.position.takeProfit.takeProfitPhase.value + 1)
announcementsModule.makeAnnoucements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.moveToPhase.value = 1
tradingEngine.current.episode.distanceToEvent.nextPhase.value = 1
return // only one event can pass at the time
}
}
}
/* Check the Move to Phase Events. */
for (let n = 0; n < phase.moveToPhaseEvents.length; n++) {
let moveToPhaseEvent = phase.moveToPhaseEvents[n]
if (moveToPhaseEvent !== undefined) {
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
let situation = moveToPhaseEvent.situations[k]
let passed
if (situation.conditions.length > 0) {
passed = true
}
passed = tradingSystem.checkConditions(situation, passed)
tradingSystem.values.push([situation.id, passed])
if (passed) {
tradingSystem.highlights.push(situation.id)
tradingSystem.highlights.push(moveToPhaseEvent.id)
tradingSystem.highlights.push(phase.id)
tradingSystem.highlights.push(takeProfit.id)
tradingSystem.highlights.push(parentNode.id)
tradingSystem.highlights.push(manageStage.id)
let moveToPhase = moveToPhaseEvent.referenceParent
if (moveToPhase !== undefined) {
for (let q = 0; q < takeProfit.phases.length; q++) {
if (takeProfit.phases[q].id === moveToPhase.id) {
tradingPositionModule.updateTakeProfit(q + 1)
}
}
} else {
tradingSystem.errors.push([moveToPhaseEvent.id, 'This Node needs to reference a Phase.'])
continue
}
announcementsModule.makeAnnoucements(moveToPhaseEvent)
/* Reset this counter */
tradingEngine.current.episode.distanceToEvent.moveToPhase.value = 1
return // only one event can pass at the time
}
}
}
}
}
}
}
function checkStopLossOrTakeProfitWasHit() {
{
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
/*
Checking what happened since the last execution. We need to know if the Stop Loss
or our Take Profit were hit.
*/
/* Stop Loss condition: Here we verify if the Stop Loss was hitted or not. */
if (
(
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Above' &&
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.stopLoss.value
) ||
(
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Below' &&
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.stopLoss.value
)
) {
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
tradingPositionModule.closingPosition('Stop Loss')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed')
announcementsModule.makeAnnoucements(strategy.closeStage)
function checkStopLossOrTakeProfitWasHit() {
{
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
/*
Checking what happened since the last execution. We need to know if the Stop Loss
or our Take Profit were hit.
*/
/* Stop Loss condition: Here we verify if the Stop Loss was hitted or not. */
if (
(
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Above' &&
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.stopLoss.value
) ||
(
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Below' &&
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.stopLoss.value
)
) {
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
tradingPositionModule.closingPosition('Stop Loss')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed')
announcementsModule.makeAnnoucements(strategy.closeStage)
return
}
/* Take Profit condition: Here we verify if the Take Profit was hit or not. */
if (
(
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Below' &&
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.takeProfit.value
) ||
(
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Above' &&
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.takeProfit.value
)
) {
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
tradingPositionModule.closingPosition('Take Profit')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed')
announcementsModule.makeAnnoucements(strategy.closeStage)
return
}
return
}
/* Take Profit condition: Here we verify if the Take Profit was hit or not. */
if (
(
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Below' &&
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.takeProfit.value
) ||
(
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Above' &&
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.takeProfit.value
)
) {
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
tradingPositionModule.closingPosition('Take Profit')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed')
announcementsModule.makeAnnoucements(strategy.closeStage)
return
}
return
}
}
}
@@ -786,12 +788,12 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
to be known before we start placing orders at the Close Stage.
*/
if (
tradingEngine.current.strategyCloseStage.status.value === 'Open' &&
(
tradingEngine.current.strategyOpenStage.status.value === 'Closed' ||
tradingEngine.current.strategyOpenStage.status.value == tradingEngine.current.strategyOpenStage.status.config.initialValue
)
) {
tradingEngine.current.strategyCloseStage.status.value === 'Open' &&
(
tradingEngine.current.strategyOpenStage.status.value === 'Closed' ||
tradingEngine.current.strategyOpenStage.status.value == tradingEngine.current.strategyOpenStage.status.config.initialValue
)
) {
/*
This will happen as long as the Close Stage is Open.
*/
@@ -893,7 +895,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
when we see at the exchange that orders were filled.
Note that the comparison is made with a Rounding Factor in order to avoid rounding problems.
*/
const ROUNDING_ERROR_CORRECTION_FACTOR = 1.001
const ROUNDING_ERROR_CORRECTION_FACTOR = 1.001
switch (tradingEngineStage.stageDefinedIn.value) {
case 'Base Asset': {
@@ -990,35 +992,50 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
closeStage(stage)
}
/*
The way the begining and end of the Stages object works is as follows:
This object begins with the last cycle, that is the current cycle diplaced
backwards to the current candle. And it ends at the end of the last cycle.
During mantainance, we add the time frame of the candle, since we assume it
will survive the 2 cycles without the end being updated. If it closes,
then we update the end to the end of the last cycle, overrinding the
mantainance if needed. If we assume that in the same cycle there will be
no closing and opening of the same type of object, then there can be no
overlap.
*/
function openStage(stage) {
/* Recording the opening at the Trading Engine Data Structure */
stage.begin.value = tradingEngine.current.episode.candle.begin.value
stage.begin.value = tradingEngine.current.episode.cycle.lastBegin.value
stage.end.value = tradingEngine.current.episode.cycle.lastEnd.value
stage.beginRate.value = tradingEngine.current.episode.candle.close.value
stage.end.value = tradingEngine.current.episode.candle.begin.value
}
function closeStage(stage) {
/* Recording the closing at the Trading Engine Data Structure */
stage.end.value = tradingEngine.current.episode.candle.begin.value
stage.end.value = tradingEngine.current.episode.cycle.lastEnd.value
stage.endRate.value = tradingEngine.current.episode.candle.close.value
}
}
function updateEnds() {
/*
Note that we can not use the cycle here because this is executed via mantain
which in turn is executed before the first cycle for this candle is set.
*/
if (tradingEngine.current.strategyTriggerStage.status.value === 'Open') {
tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.episode.cycle.end.value
tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.strategyTriggerStage.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.strategyTriggerStage.endRate.value = tradingEngine.current.episode.candle.close.value
}
if (tradingEngine.current.strategyOpenStage.status.value === 'Open') {
tradingEngine.current.strategyOpenStage.end.value = tradingEngine.current.episode.cycle.end.value
tradingEngine.current.strategyOpenStage.end.value = tradingEngine.current.strategyOpenStage.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.strategyOpenStage.endRate.value = tradingEngine.current.episode.candle.close.value
}
if (tradingEngine.current.strategyManageStage.status.value === 'Open') {
tradingEngine.current.strategyManageStage.end.value = tradingEngine.current.episode.cycle.end.value
tradingEngine.current.strategyManageStage.end.value = tradingEngine.current.strategyManageStage.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.strategyManageStage.endRate.value = tradingEngine.current.episode.candle.close.value
}
if (tradingEngine.current.strategyCloseStage.status.value === 'Open') {
tradingEngine.current.strategyCloseStage.end.value = tradingEngine.current.episode.cycle.end.value
tradingEngine.current.strategyCloseStage.end.value = tradingEngine.current.strategyCloseStage.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.strategyCloseStage.endRate.value = tradingEngine.current.episode.candle.close.value
}
}
@@ -13,15 +13,18 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
}
let tradingEngine
let sessionParameters
return thisObject
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
}
function finalize() {
tradingEngine = undefined
sessionParameters = undefined
}
function mantain() {
@@ -34,11 +37,14 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
}
function openStrategy(index, situationName, strategyName) {
/* Starting begin and end */
tradingEngine.current.strategy.begin.value = tradingEngine.current.episode.cycle.lastBegin.value
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.cycle.lastEnd.value
/* Recording the opening at the Trading Engine Data Structure */
tradingEngine.current.strategy.status.value = 'Open'
tradingEngine.current.strategy.serialNumber.value = tradingEngine.current.episode.episodeCounters.strategies.value
tradingEngine.current.strategy.identifier.value = global.UNIQUE_ID()
tradingEngine.current.strategy.begin.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.end.value
tradingEngine.current.strategy.beginRate.value = tradingEngine.current.episode.candle.min.value
tradingEngine.current.strategy.index.value = index
@@ -52,7 +58,7 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
function closeStrategy(exitType) {
tradingEngine.current.strategy.status.value = 'Closed'
tradingEngine.current.strategy.exitType.value = exitType
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.begin.value
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.cycle.lastEnd.value
tradingEngine.current.strategy.endRate.value = tradingEngine.current.episode.candle.min.value
/*
Now that the strategy is closed, it is the right time to move this strategy from current to last at the Trading Engine data structure.
@@ -62,7 +68,7 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
function updateEnds() {
if (tradingEngine.current.strategy.status.value === 'Open') {
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.end.value
tradingEngine.current.strategy.end.value = tradingEngine.current.strategy.end.value + sessionParameters.timeFrame.config.value
tradingEngine.current.strategy.endRate.value = tradingEngine.current.episode.candle.close.value
}
}