Take Profit and Stop Loss being Plotted
This commit is contained in:
1 parent
3badcfb2a5
commit
03b69d0a0c
6 files changed
+272
-170
No files matched your search
@@ -7,8 +7,6 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
let thisObject = {
|
||||
setCurrentCandle: setCurrentCandle,
|
||||
updateEpisodeCountersAndStatistics: updateEpisodeCountersAndStatistics,
|
||||
resetPositionCountersAndStatistics: resetPositionCountersAndStatistics,
|
||||
updatePositionCountersAndStatistics: updatePositionCountersAndStatistics,
|
||||
updateDistanceToEventsCounters: updateDistanceToEventsCounters,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
@@ -98,6 +96,7 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
node.value = node.config.initialValue
|
||||
}
|
||||
}
|
||||
node.initialize = initializeNode // This will allow anyone to initialize this node and its children.
|
||||
|
||||
/* Now we go down through all this node children */
|
||||
let nodeDefinition = bot.APP_SCHEMA_MAP.get(node.type)
|
||||
@@ -137,26 +136,6 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
tradingEngine.episode.episodeStatistics.days.value = tradingEngine.episode.episodeCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
|
||||
function resetPositionCountersAndStatistics() {
|
||||
/* Keeping Position Counters Up-to-date */
|
||||
if (
|
||||
(tradingEngine.current.strategy.stageType.value === 'Open Stage' || tradingEngine.current.strategy.stageType.value === 'Manage Stage')
|
||||
) { return }
|
||||
|
||||
tradingEngine.current.position.positionCounters.periods.value = tradingEngine.current.position.positionCounters.periods.config.initialValue
|
||||
tradingEngine.current.position.positionStatistics.days.value = tradingEngine.current.position.positionStatistics.days.config.initialValue
|
||||
}
|
||||
|
||||
function updatePositionCountersAndStatistics() {
|
||||
/* Keeping Position Counters Up-to-date */
|
||||
if (
|
||||
(tradingEngine.current.strategy.stageType.value === 'Open Stage' || tradingEngine.current.strategy.stageType.value === 'Manage Stage')
|
||||
) {
|
||||
tradingEngine.current.position.positionCounters.periods.value++
|
||||
tradingEngine.current.position.positionStatistics.days.value = tradingEngine.current.position.positionCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
}
|
||||
|
||||
function updateDistanceToEventsCounters() {
|
||||
/* Keeping Distance Counters Up-to-date */
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
exports.newTradingPosition = function newTradingPosition(bot, logger) {
|
||||
/*
|
||||
This module packages all functions related to Positions.
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Position'
|
||||
let thisObject = {
|
||||
openPosition: openPosition,
|
||||
closePosition: closePosition,
|
||||
applyStopLossFormula: applyStopLossFormula,
|
||||
applyTakeProfitFormula: applyTakeProfitFormula,
|
||||
preventStopLossDistortion: preventStopLossDistortion,
|
||||
applySlippageToStopLoss: applySlippageToStopLoss,
|
||||
preventTakeProfitDistortion: preventTakeProfitDistortion,
|
||||
applySlippageToTakeProfit: applySlippageToTakeProfit,
|
||||
updateStopLoss: updateStopLoss,
|
||||
updateTakeProfit: updateTakeProfit,
|
||||
updateSizeAndRate: updateSizeAndRate,
|
||||
applySlippageToRate: applySlippageToRate,
|
||||
updateEnds: updateEnds,
|
||||
updateStatus: updateStatus,
|
||||
updateCounters: updateCounters,
|
||||
updateStatistics: updateStatistics,
|
||||
resetPosition: resetPosition,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let tradingEngine
|
||||
let sessionParameters
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize() {
|
||||
tradingEngine = bot.simulationState.tradingEngine
|
||||
sessionParameters = bot.SESSION.parameters
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
tradingEngine = undefined
|
||||
sessionParameters = undefined
|
||||
}
|
||||
|
||||
function openPosition(situationName) {
|
||||
tradingEngine.current.position.status.value = 'Open'
|
||||
tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
|
||||
tradingEngine.current.position.situationName.value = situationName
|
||||
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'Open Stage'
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'Open Stage'
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value = 0
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value = 0
|
||||
}
|
||||
|
||||
function closePosition(exitType) {
|
||||
tradingEngine.current.position.status.value = 'Closed'
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.position.exitType.value = exitType
|
||||
}
|
||||
|
||||
function resetPosition() {
|
||||
tradingEngine.current.position.initialize(tradingEngine.current.position)
|
||||
}
|
||||
|
||||
function applyStopLossFormula(formulas, formulaId) {
|
||||
tradingEngine.current.position.stopLoss.value = formulas.get(formulaId)
|
||||
}
|
||||
|
||||
function applyTakeProfitFormula(formulas, formulaId) {
|
||||
tradingEngine.current.position.takeProfit.value = formulas.get(formulaId)
|
||||
}
|
||||
|
||||
function updateStopLoss(phase, stage) {
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value = phase
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = stage
|
||||
}
|
||||
|
||||
function updateTakeProfit(phase, stage) {
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value = phase
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = stage
|
||||
}
|
||||
|
||||
function updateSizeAndRate(size, rate) {
|
||||
tradingEngine.current.position.size.value = size
|
||||
tradingEngine.current.position.rate.value = rate
|
||||
}
|
||||
|
||||
function applySlippageToRate() {
|
||||
let slippageAmount = tradingEngine.current.position.rate.value * bot.SESSION.parameters.slippage.config.positionRate / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value - slippageAmount
|
||||
} else {
|
||||
tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value + slippageAmount
|
||||
}
|
||||
}
|
||||
|
||||
function preventStopLossDistortion() {
|
||||
/*
|
||||
Hit Point Validation
|
||||
|
||||
This prevents misscalculations when a formula places the stop loss in this case way beyond the market price.
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
if (tradingEngine.current.position.stopLoss.value < tradingEngine.current.candle.min.value) {
|
||||
tradingEngine.current.position.stopLoss.value = tradingEngine.current.candle.min.value
|
||||
}
|
||||
} else {
|
||||
if (tradingEngine.current.position.stopLoss.value > tradingEngine.current.candle.max.value) {
|
||||
tradingEngine.current.position.stopLoss.value = tradingEngine.current.candle.max.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applySlippageToStopLoss() {
|
||||
let slippedStopLoss = tradingEngine.current.position.stopLoss.value
|
||||
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedStopLoss * bot.SESSION.parameters.slippage.config.stopLoss / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
slippedStopLoss = slippedStopLoss + slippageAmount
|
||||
} else {
|
||||
slippedStopLoss = slippedStopLoss - slippageAmount
|
||||
}
|
||||
|
||||
tradingEngine.current.position.endRate.value = slippedStopLoss
|
||||
}
|
||||
|
||||
function preventTakeProfitDistortion() {
|
||||
/*
|
||||
Hit Point Validation:
|
||||
|
||||
This prevents misscalculations when a formula places the take profit in this case way beyond the market price.
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
if (tradingEngine.current.position.takeProfit.value > tradingEngine.current.candle.max.value) {
|
||||
tradingEngine.current.position.takeProfit.value = tradingEngine.current.candle.max.value
|
||||
}
|
||||
} else {
|
||||
if (tradingEngine.current.position.takeProfit.value < tradingEngine.current.candle.min.value) {
|
||||
tradingEngine.current.position.takeProfit.value = tradingEngine.current.candle.min.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applySlippageToTakeProfit() {
|
||||
let slippedTakeProfit = tradingEngine.current.position.takeProfit.value
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedTakeProfit * bot.SESSION.parameters.slippage.config.takeProfit / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
slippedTakeProfit = slippedTakeProfit + slippageAmount
|
||||
} else {
|
||||
slippedTakeProfit = slippedTakeProfit - slippageAmount
|
||||
}
|
||||
|
||||
tradingEngine.current.position.endRate.value = slippedTakeProfit
|
||||
}
|
||||
|
||||
function updateEnds() {
|
||||
if (tradingEngine.current.position.status.value === 'Open') {
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatus() {
|
||||
if (tradingEngine.current.position.status.value === 'Closed') {
|
||||
resetPosition()
|
||||
}
|
||||
}
|
||||
|
||||
function updateCounters() {
|
||||
if (tradingEngine.current.position.status.value === 'Open') {
|
||||
tradingEngine.current.position.positionCounters.periods.value++
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatistics() {
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
tradingEngine.current.position.positionStatistics.profitLoss.value = tradingEngine.current.balance.baseAsset.value - tradingEngine.previous.balance.baseAsset.value
|
||||
tradingEngine.current.position.positionStatistics.ROI.value = tradingEngine.current.position.positionStatistics.profitLoss.value * 100 / tradingEngine.current.position.size.value
|
||||
} else {
|
||||
tradingEngine.current.position.positionStatistics.profitLoss.value = tradingEngine.current.balance.quotedAsset.value - tradingEngine.previous.balance.quotedAsset.value
|
||||
tradingEngine.current.position.positionStatistics.ROI.value = tradingEngine.current.position.positionStatistics.profitLoss.value * 100 / tradingEngine.current.position.size.value
|
||||
}
|
||||
tradingEngine.current.position.positionStatistics.days.value = tradingEngine.current.position.positionCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,6 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
let product = dataset.parentNode
|
||||
let outputDatasetArray = outputDatasetsMap.get(product.config.codeName)
|
||||
|
||||
if (product.config.codeName === 'Strategy-Objects') {
|
||||
let a = 1
|
||||
}
|
||||
|
||||
if (bot.processingDailyFiles === true && dataset.config.type === 'Daily Files') {
|
||||
persistRecord()
|
||||
}
|
||||
@@ -91,6 +87,9 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
}
|
||||
|
||||
function scanRecordDefinition(product) {
|
||||
if (product.config.codeName === 'Position-Objects') {
|
||||
let a = 1
|
||||
}
|
||||
/*
|
||||
The Product Root Node is the root of the node hiriarchy branch that we need to look at
|
||||
in order to fnd the node where we are going to extract the value.
|
||||
@@ -166,6 +165,9 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
if (recordProperty.config.isString !== true && Array.isArray(value) !== true) {
|
||||
value = safeNumericValue(value)
|
||||
}
|
||||
if (recordProperty.config.isString === true && Array.isArray(value) !== true) {
|
||||
value = safeStringValue(value)
|
||||
}
|
||||
record.push(value)
|
||||
}
|
||||
return record
|
||||
@@ -191,4 +193,18 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
function safeStringValue(value) {
|
||||
/*
|
||||
The purpose of this function is to check that value variable does not have a value that
|
||||
will later break the JSON format of files where this is going to be stored at.
|
||||
*/
|
||||
if (value === undefined) {
|
||||
value = ''
|
||||
}
|
||||
if (value === null) {
|
||||
value = ''
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -186,8 +186,6 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
tradingSystemModule.calculateTakeProfit()
|
||||
}
|
||||
|
||||
tradingEngineModule.resetPositionCountersAndStatistics()
|
||||
tradingEngineModule.updatePositionCountersAndStatistics()
|
||||
tradingEngineModule.updateDistanceToEventsCounters()
|
||||
|
||||
/* Checking if Stop or Take Profit were hit */
|
||||
@@ -198,6 +196,16 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
/* Taking a Position */
|
||||
if (takingPosition === true) {
|
||||
tradingSystemModule.getReadyToTakePosition()
|
||||
/*
|
||||
Whem we calculated all the formulas at the begining of the loop, we didn't know
|
||||
we were going to take position in this same loop cycle. Some might formulas depends on
|
||||
calculations that are triggered only when we are taking position. For that reason
|
||||
we will calculate all formulas again, and after that the Stop Loss and Take Profit.
|
||||
*/
|
||||
tradingSystemModule.evalFormulas()
|
||||
tradingSystemModule.calculateTakeProfit()
|
||||
tradingSystemModule.calculateStopLoss()
|
||||
|
||||
tradingExecutionModule.takePosition()
|
||||
tradingSystemModule.takePosition()
|
||||
takingPosition = false
|
||||
|
||||
@@ -40,17 +40,15 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger) {
|
||||
tradingEngine.current.strategy.strategyName.value = strategyName
|
||||
}
|
||||
|
||||
function closeStrategy() {
|
||||
function closeStrategy(exitType) {
|
||||
tradingEngine.current.strategy.status.value = 'Closed'
|
||||
tradingEngine.current.strategy.exitType.value = exitType
|
||||
tradingEngine.current.strategy.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.min.value
|
||||
}
|
||||
|
||||
function resetStrategy() {
|
||||
tradingEngine.current.strategy.status.value = tradingEngine.current.strategy.status.config.initialValue
|
||||
tradingEngine.current.strategy.stageType.value = tradingEngine.current.strategy.stageType.config.initialValue
|
||||
tradingEngine.current.strategy.index.value = tradingEngine.current.strategy.index.config.initialValue
|
||||
tradingEngine.current.strategy.strategyCounters.periods.value = tradingEngine.current.strategy.strategyCounters.periods.config.initialValue
|
||||
tradingEngine.current.strategy.initialize(tradingEngine.current.strategy)
|
||||
}
|
||||
|
||||
function updateEnds() {
|
||||
|
||||
@@ -41,6 +41,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
const TRADING_STRATEGY_MODULE = require('./TradingStrategy.js')
|
||||
let tradingStrategyModule = TRADING_STRATEGY_MODULE.newTradingStrategy(bot, logger)
|
||||
|
||||
const TRADING_POSITION_MODULE = require('./TradingPosition.js')
|
||||
let tradingPositionModule = TRADING_POSITION_MODULE.newTradingPosition(bot, logger)
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize() {
|
||||
@@ -49,12 +52,16 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
sessionParameters = bot.SESSION.parameters
|
||||
|
||||
tradingStrategyModule.initialize()
|
||||
tradingPositionModule.initialize()
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
tradingStrategyModule.finalize()
|
||||
tradingStrategyModule = undefined
|
||||
|
||||
tradingPositionModule.finalize()
|
||||
tradingPositionModule = undefined
|
||||
|
||||
chart = undefined
|
||||
|
||||
conditions = undefined
|
||||
@@ -89,7 +96,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
}
|
||||
|
||||
function mantainPositions() {
|
||||
|
||||
tradingPositionModule.updateStatus()
|
||||
tradingPositionModule.updateCounters()
|
||||
tradingPositionModule.updateEnds()
|
||||
}
|
||||
|
||||
function evalConditions() {
|
||||
@@ -333,7 +342,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
tradingSystem.highlights.push(triggerStage.triggerOff.id)
|
||||
tradingSystem.highlights.push(triggerStage.id)
|
||||
|
||||
tradingStrategyModule.closeStrategy()
|
||||
tradingStrategyModule.closeStrategy('Trigger Off')
|
||||
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value = 1
|
||||
|
||||
@@ -353,7 +362,10 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
|
||||
function checkTakePosition() {
|
||||
/* Take Position Condition */
|
||||
if (tradingEngine.current.strategy.stageType.value === 'Trigger Stage') {
|
||||
if (
|
||||
tradingEngine.current.strategy.stageType.value === 'Trigger Stage' &&
|
||||
tradingEngine.current.strategy.status.value === 'Open'
|
||||
) {
|
||||
let strategy = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value]
|
||||
let triggerStage = strategy.triggerStage
|
||||
|
||||
@@ -383,12 +395,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
tradingSystem.highlights.push(triggerStage.id)
|
||||
|
||||
tradingStrategyModule.updateStageType('Open Stage')
|
||||
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'Open Stage'
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'Open Stage'
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value = 0
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value = 0
|
||||
tradingEngine.current.position.situationName.value = situation.name
|
||||
tradingPositionModule.openPosition(situation.name)
|
||||
|
||||
/* TODO See what to do with this:
|
||||
checkAnnouncements(triggerStage.takePosition)
|
||||
@@ -470,8 +477,8 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
tradingSystem.highlights.push(parentNode.id)
|
||||
tradingSystem.highlights.push(stage.id)
|
||||
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value++
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'Manage Stage'
|
||||
tradingPositionModule.updateStopLoss(tradingEngine.current.position.stopLoss.stopLossPhase.value + 1, 'Manage Stage')
|
||||
|
||||
if (tradingEngine.current.position.takeProfit.takeProfitPhase.value > 0) {
|
||||
tradingStrategyModule.updateStageType('Manage Stage')
|
||||
/* TODO ANNOUNCEMENT
|
||||
@@ -521,7 +528,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
if (moveToPhase !== undefined) {
|
||||
for (let q = 0; q < stopLoss.phases.length; q++) {
|
||||
if (stopLoss.phases[q].id === moveToPhase.id) {
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value = q + 1
|
||||
tradingPositionModule.updateStopLoss(q + 1, 'Manage Stage')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -529,7 +536,6 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
continue
|
||||
}
|
||||
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'Manage Stage'
|
||||
if (tradingEngine.current.position.takeProfit.takeProfitPhase.value > 0) {
|
||||
tradingStrategyModule.updateStageType('Manage Stage')
|
||||
/* TODO ANNOUNCEMENT
|
||||
@@ -572,7 +578,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
if (phase !== undefined) {
|
||||
if (phase.formula !== undefined) {
|
||||
let previousValue = tradingEngine.current.position.stopLoss.value
|
||||
tradingEngine.current.position.stopLoss.value = formulas.get(phase.formula.id)
|
||||
tradingPositionModule.applyStopLossFormula(formulas, phase.formula.id)
|
||||
|
||||
/* TODO ANNOUNCEMENTS
|
||||
if (tradingEngine.current.position.stopLoss.value !== previousValue) {
|
||||
@@ -648,8 +654,8 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
tradingSystem.highlights.push(parentNode.id)
|
||||
tradingSystem.highlights.push(stage.id)
|
||||
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value++
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'Manage Stage'
|
||||
tradingPositionModule.updateTakeProfit(tradingEngine.current.position.takeProfit.takeProfitPhase.value + 1, 'Manage Stage')
|
||||
|
||||
if (tradingEngine.current.position.stopLoss.stopLossPhase.value > 0) {
|
||||
tradingStrategyModule.updateStageType('Manage Stage')
|
||||
/* TODO ANNOUNCEMENT
|
||||
@@ -698,7 +704,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
if (moveToPhase !== undefined) {
|
||||
for (let q = 0; q < takeProfit.phases.length; q++) {
|
||||
if (takeProfit.phases[q].id === moveToPhase.id) {
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value = q + 1
|
||||
tradingPositionModule.updateTakeProfit(q + 1, 'Manage Stage')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -706,7 +712,6 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
continue
|
||||
}
|
||||
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'Manage Stage'
|
||||
if (tradingEngine.current.position.stopLoss.stopLossPhase.value > 0) {
|
||||
tradingStrategyModule.updateStageType('Manage Stage')
|
||||
/* TODO ANNOUNCEMENT
|
||||
@@ -748,8 +753,8 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
|
||||
if (phase !== undefined) {
|
||||
if (phase.formula !== undefined) {
|
||||
let previousValue = tradingEngine.current.position.stopLoss.value
|
||||
tradingEngine.current.position.takeProfit.value = formulas.get(phase.formula.id)
|
||||
let previousValue = tradingEngine.current.position.takeProfit.value
|
||||
tradingPositionModule.applyTakeProfitFormula(formulas, phase.formula.id)
|
||||
|
||||
/* TODO ANNOUNCEMENTS
|
||||
if (tradingEngine.current.position.takeProfit.value !== previousValue) {
|
||||
@@ -776,45 +781,16 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
(!bot.sessionAndMarketBaseAssetsAreEqual && tradingEngine.current.candle.min.value <= tradingEngine.current.position.stopLoss.value)
|
||||
) {
|
||||
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
|
||||
/*
|
||||
Hit Point Validation
|
||||
|
||||
This prevents misscalculations when a formula places the stop loss in this case way beyond the market price.
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
if (tradingEngine.current.position.stopLoss.value < tradingEngine.current.candle.min.value) {
|
||||
tradingEngine.current.position.stopLoss.value = tradingEngine.current.candle.min.value
|
||||
}
|
||||
} else {
|
||||
if (tradingEngine.current.position.stopLoss.value > tradingEngine.current.candle.max.value) {
|
||||
tradingEngine.current.position.stopLoss.value = tradingEngine.current.candle.max.value
|
||||
}
|
||||
}
|
||||
|
||||
let slippedStopLoss = tradingEngine.current.position.stopLoss.value
|
||||
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedStopLoss * bot.SESSION.parameters.slippage.config.stopLoss / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
slippedStopLoss = slippedStopLoss + slippageAmount
|
||||
} else {
|
||||
slippedStopLoss = slippedStopLoss - slippageAmount
|
||||
}
|
||||
|
||||
tradingEngine.current.position.endRate.value = slippedStopLoss
|
||||
tradingPositionModule.preventStopLossDistortion()
|
||||
tradingPositionModule.applySlippageToStopLoss()
|
||||
tradingPositionModule.closePosition('Stop Loss')
|
||||
|
||||
tradingStrategyModule.updateStageType('Close Stage')
|
||||
|
||||
/* TODO ANNOUNCEMENT
|
||||
checkAnnouncements(strategy.closeStage, 'Stop')
|
||||
*/
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'No Stage'
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'No Stage'
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.position.status.value = 1
|
||||
tradingEngine.current.position.exitType.value = 1
|
||||
|
||||
return true // This means that the STOP was hit.
|
||||
}
|
||||
|
||||
@@ -824,46 +800,16 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
(!bot.sessionAndMarketBaseAssetsAreEqual && tradingEngine.current.candle.max.value >= tradingEngine.current.position.takeProfit.value)
|
||||
) {
|
||||
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
|
||||
/*
|
||||
Hit Point Validation:
|
||||
|
||||
This prevents misscalculations when a formula places the take profit in this case way beyond the market price.
|
||||
If we take the stop loss value at those situation would be a huge distortion of facts.
|
||||
*/
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
if (tradingEngine.current.position.takeProfit.value > tradingEngine.current.candle.max.value) {
|
||||
tradingEngine.current.position.takeProfit.value = tradingEngine.current.candle.max.value
|
||||
}
|
||||
} else {
|
||||
if (tradingEngine.current.position.takeProfit.value < tradingEngine.current.candle.min.value) {
|
||||
tradingEngine.current.position.takeProfit.value = tradingEngine.current.candle.min.value
|
||||
}
|
||||
}
|
||||
|
||||
let slippedTakeProfit = tradingEngine.current.position.takeProfit.value
|
||||
/* Apply the Slippage */
|
||||
let slippageAmount = slippedTakeProfit * bot.SESSION.parameters.slippage.config.takeProfit / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
slippedTakeProfit = slippedTakeProfit + slippageAmount
|
||||
} else {
|
||||
slippedTakeProfit = slippedTakeProfit - slippageAmount
|
||||
}
|
||||
|
||||
tradingEngine.current.position.endRate.value = slippedTakeProfit
|
||||
tradingPositionModule.preventTakeProfitDistortion()
|
||||
tradingPositionModule.applySlippageToTakeProfit()
|
||||
tradingPositionModule.closePosition('Take Profit')
|
||||
|
||||
tradingStrategyModule.updateStageType('Close Stage')
|
||||
|
||||
/* TODO ANNOUNCEMENT
|
||||
checkAnnouncements(strategy.closeStage, 'Take Profit')
|
||||
*/
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'No Stage'
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'No Stage'
|
||||
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.position.status.value = 1
|
||||
tradingEngine.current.position.exitType.value = 2
|
||||
|
||||
addToSnapshots = true
|
||||
return true // This means that the Take Profit was hit.
|
||||
}
|
||||
}
|
||||
@@ -872,31 +818,20 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
}
|
||||
|
||||
function getReadyToTakePosition() {
|
||||
/* Updating Episode Counters */
|
||||
tradingEngine.episode.episodeCounters.positions.value++
|
||||
|
||||
/* Inicializing this counter */
|
||||
tradingEngine.current.distanceToEvent.takePosition.value = 1
|
||||
|
||||
/* Position size and rate */
|
||||
tradingEngine.current.position.size.value = getPositionSize()
|
||||
tradingEngine.current.position.rate.value = getPositionRate()
|
||||
tradingPositionModule.updateSizeAndRate(getPositionSize(), getPositionRate())
|
||||
|
||||
/* We take what was calculated at the formula and apply the slippage. */
|
||||
let slippageAmount = tradingEngine.current.position.rate.value * bot.SESSION.parameters.slippage.config.positionRate / 100
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
tradingEngine.current.position.rate.value = tradingEngine.current.position.rate.value - slippageAmount
|
||||
} else {
|
||||
tradingEngine.current.position.rate.value = tradingEngine.current.position.rate.value + slippageAmount
|
||||
}
|
||||
|
||||
/* Update the position information. */
|
||||
tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value
|
||||
tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value
|
||||
/* We take what was calculated at the formula of position rate and apply the slippage. */
|
||||
tradingPositionModule.applySlippageToRate()
|
||||
}
|
||||
|
||||
function takePosition() {
|
||||
calculateTakeProfit() // TODO: Check if this is really necesary
|
||||
calculateStopLoss() // TODO: Check if this is really necesary
|
||||
|
||||
tradingEngine.previous.balance.baseAsset.value = tradingEngine.current.balance.baseAsset.value
|
||||
tradingEngine.previous.balance.quotedAsset.value = tradingEngine.current.balance.quotedAsset.value
|
||||
|
||||
@@ -927,70 +862,44 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
|
||||
}
|
||||
|
||||
function closePosition() {
|
||||
tradingEngine.episode.episodeCounters.positions.value++
|
||||
|
||||
/* We calculate the new balances after the position is closed. */
|
||||
let feePaid = 0
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
|
||||
feePaid = tradingEngine.current.balance.quotedAsset.value / tradingEngine.current.position.endRate.value * bot.SESSION.parameters.feeStructure.config.taker / 100
|
||||
|
||||
tradingEngine.current.balance.baseAsset.value = tradingEngine.current.balance.baseAsset.value + tradingEngine.current.balance.quotedAsset.value / tradingEngine.current.position.endRate.value - feePaid
|
||||
tradingEngine.current.balance.quotedAsset.value = 0
|
||||
} else {
|
||||
|
||||
feePaid = tradingEngine.current.balance.baseAsset.value * tradingEngine.current.position.endRate.value * bot.SESSION.parameters.feeStructure.config.taker / 100
|
||||
|
||||
tradingEngine.current.balance.quotedAsset.value = tradingEngine.current.balance.quotedAsset.value + tradingEngine.current.balance.baseAsset.value * tradingEngine.current.position.endRate.value - feePaid
|
||||
tradingEngine.current.balance.baseAsset.value = 0
|
||||
}
|
||||
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
tradingEngine.last.position.positionStatistics.profitLoss.value = tradingEngine.current.balance.baseAsset.value - tradingEngine.previous.balance.baseAsset.value
|
||||
tradingEngine.last.position.positionStatistics.ROI.value = tradingEngine.last.position.positionStatistics.profitLoss.value * 100 / tradingEngine.current.position.size.value
|
||||
if (isNaN(tradingEngine.last.position.positionStatistics.ROI.value)) { tradingEngine.last.position.positionStatistics.ROI.value = 0 }
|
||||
tradingEngine.episode.episodeStatistics.profitLoss.value = tradingEngine.current.balance.baseAsset.value - sessionParameters.sessionBaseAsset.config.initialBalance
|
||||
} else {
|
||||
tradingEngine.last.position.positionStatistics.profitLoss.value = tradingEngine.current.balance.quotedAsset.value - tradingEngine.previous.balance.quotedAsset.value
|
||||
tradingEngine.last.position.positionStatistics.ROI.value = tradingEngine.last.position.positionStatistics.profitLoss.value * 100 / tradingEngine.current.position.size.value
|
||||
if (isNaN(tradingEngine.last.position.positionStatistics.ROI.value)) { tradingEngine.last.position.positionStatistics.ROI.value = 0 }
|
||||
tradingEngine.episode.episodeStatistics.profitLoss.value = tradingEngine.current.balance.quotedAsset.value - sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
}
|
||||
|
||||
tradingEngine.current.position.positionStatistics.ROI.value = tradingEngine.last.position.positionStatistics.ROI.value
|
||||
tradingPositionModule.updateStatistics()
|
||||
|
||||
/* Recalculating Episode Counters */
|
||||
if (tradingEngine.last.position.positionStatistics.profitLoss.value > 0) {
|
||||
tradingEngine.episode.episodeCounters.hits.value++
|
||||
} else {
|
||||
tradingEngine.episode.episodeCounters.fails.value++
|
||||
}
|
||||
|
||||
/* Recalculating Episode Statistics */
|
||||
if (bot.sessionAndMarketBaseAssetsAreEqual) {
|
||||
tradingEngine.episode.episodeStatistics.profitLoss.value = tradingEngine.current.balance.baseAsset.value - sessionParameters.sessionBaseAsset.config.initialBalance
|
||||
tradingEngine.episode.episodeStatistics.ROI.value = (sessionParameters.sessionBaseAsset.config.initialBalance + tradingEngine.episode.episodeStatistics.profitLoss.value) / sessionParameters.sessionBaseAsset.config.initialBalance - 1
|
||||
tradingEngine.episode.episodeStatistics.hitRatio.value = tradingEngine.episode.episodeCounters.hits.value / tradingEngine.episode.episodeCounters.positions.value
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days.value * 365
|
||||
} else {
|
||||
tradingEngine.episode.episodeStatistics.profitLoss.value = tradingEngine.current.balance.quotedAsset.value - sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
tradingEngine.episode.episodeStatistics.ROI.value = (sessionParameters.sessionQuotedAsset.config.initialBalance + tradingEngine.episode.episodeStatistics.profitLoss.value) / sessionParameters.sessionQuotedAsset.config.initialBalance - 1
|
||||
tradingEngine.episode.episodeStatistics.hitRatio.value = tradingEngine.episode.episodeCounters.hits.value / tradingEngine.episode.episodeCounters.positions.value
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days.value * 365
|
||||
}
|
||||
|
||||
tradingEngine.current.position.stopLoss.value = 0
|
||||
tradingEngine.current.position.takeProfit.value = 0
|
||||
|
||||
tradingEngine.current.position.rate.value = 0
|
||||
tradingEngine.current.position.size.value = 0
|
||||
|
||||
tradingEngine.current.position.stopLoss.stopLossStage.value = 'No Stage'
|
||||
tradingEngine.current.position.takeProfit.takeProfitStage.value = 'No Stage'
|
||||
tradingEngine.current.position.stopLoss.stopLossPhase.value = -1
|
||||
tradingEngine.current.position.takeProfit.takeProfitPhase.value = -1
|
||||
|
||||
}
|
||||
|
||||
function exitStrategyAfterPosition() {
|
||||
if (tradingEngine.current.strategy.stageType.value === 'Close Stage') {
|
||||
tradingStrategyModule.closeStrategy()
|
||||
tradingStrategyModule.closeStrategy('Position Closed')
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value = 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user