199 lines
8.5 KiB
JavaScript
199 lines
8.5 KiB
JavaScript
exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEngineModule) {
|
|
/*
|
|
This module packages all functions related to Positions.
|
|
*/
|
|
const MODULE_NAME = 'Trading Position'
|
|
let thisObject = {
|
|
openPosition: openPosition,
|
|
closingPosition: closingPosition,
|
|
closePosition: closePosition,
|
|
applyStopLossFormula: applyStopLossFormula,
|
|
applyTakeProfitFormula: applyTakeProfitFormula,
|
|
preventStopLossDistortion: preventStopLossDistortion,
|
|
applySlippageToStopLoss: applySlippageToStopLoss,
|
|
preventTakeProfitDistortion: preventTakeProfitDistortion,
|
|
applySlippageToTakeProfit: applySlippageToTakeProfit,
|
|
updateStopLoss: updateStopLoss,
|
|
updateTakeProfit: updateTakeProfit,
|
|
updateSizeAndRate: updateSizeAndRate,
|
|
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.serialNumber.value = tradingEngine.episode.episodeCounters.positions.value
|
|
tradingEngine.current.position.identifier.value = global.UNIQUE_ID()
|
|
tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value
|
|
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
|
|
|
tradingEngine.current.position.situationName.value = situationName
|
|
|
|
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 closingPosition(exitType) {
|
|
tradingEngine.current.position.status.value = 'Closing'
|
|
tradingEngine.current.position.exitType.value = exitType
|
|
}
|
|
|
|
function closePosition() {
|
|
tradingEngine.current.position.status.value = 'Closed'
|
|
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
|
/*
|
|
Now that the position is closed, it is the right time to move this position from current to last at the Trading Engine data structure.
|
|
*/
|
|
tradingEngineModule.cloneValues(tradingEngine.current.position, tradingEngine.last.position)
|
|
}
|
|
|
|
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 = global.PRECISE(size, 10)
|
|
tradingEngine.current.position.rate.value = global.PRECISE(rate, 10)
|
|
|
|
tradingEngine.current.position.beginRate.value = tradingEngine.current.position.rate.value
|
|
}
|
|
|
|
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
|
|
if (tradingEngine.current.position.positionStatistics.ROI.value > 0) {
|
|
tradingEngine.current.position.positionStatistics.hitFail.value = 'HIT'
|
|
} else {
|
|
tradingEngine.current.position.positionStatistics.hitFail.value = 'FAIL'
|
|
}
|
|
}
|
|
} |