Final Polishing Iteration done
This commit is contained in:
1 parent
b0add9b805
commit
b312313586
13 files changed
+359
-333
No files matched your search
@@ -5,10 +5,10 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Engine'
|
||||
let thisObject = {
|
||||
mantain: mantain,
|
||||
getNodeById: getNodeById,
|
||||
cloneValues: cloneValues,
|
||||
setCurrentCandle: setCurrentCandle,
|
||||
updateDistanceToEventsCounters: updateDistanceToEventsCounters,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
@@ -20,15 +20,16 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
return thisObject
|
||||
|
||||
function initialize() {
|
||||
/* Here we will go through all the nodes in the Trading Engine hiriarchy and apply the initial value to the value property when needed */
|
||||
|
||||
tradingEngine = bot.simulationState.tradingEngine
|
||||
sessionParameters = bot.SESSION.parameters
|
||||
|
||||
if (bot.FIRST_EXECUTION === true) {
|
||||
/*
|
||||
Here we will go through all the nodes in the Trading Engine hiriarchy and
|
||||
apply the initial value to the value property when needed
|
||||
*/
|
||||
initializeNode(tradingEngine)
|
||||
tradingEngine.current.balance.baseAsset.value = sessionParameters.sessionBaseAsset.config.initialBalance
|
||||
tradingEngine.current.balance.quotedAsset.value = sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,19 +39,21 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
nodesMap = undefined
|
||||
}
|
||||
|
||||
function mantain() {
|
||||
updateDistanceToEventsCounters()
|
||||
}
|
||||
|
||||
function getNodeById(NodeId) {
|
||||
return nodesMap.get(NodeId)
|
||||
}
|
||||
|
||||
function setCurrentCandle(candle) {
|
||||
cloneValues(tradingEngine.current.candle, tradingEngine.previous.candle)
|
||||
|
||||
tradingEngine.current.candle.begin.value = candle.begin
|
||||
tradingEngine.current.candle.end.value = candle.end
|
||||
tradingEngine.current.candle.open.value = candle.open
|
||||
tradingEngine.current.candle.close.value = candle.close
|
||||
tradingEngine.current.candle.min.value = candle.min
|
||||
tradingEngine.current.candle.max.value = candle.max
|
||||
tradingEngine.current.episode.candle.begin.value = candle.begin
|
||||
tradingEngine.current.episode.candle.end.value = candle.end
|
||||
tradingEngine.current.episode.candle.open.value = candle.open
|
||||
tradingEngine.current.episode.candle.close.value = candle.close
|
||||
tradingEngine.current.episode.candle.min.value = candle.min
|
||||
tradingEngine.current.episode.candle.max.value = candle.max
|
||||
}
|
||||
|
||||
function cloneValues(originNode, destinationNode) {
|
||||
@@ -143,57 +146,57 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
function updateDistanceToEventsCounters() {
|
||||
/* Keeping Distance Counters Up-to-date while avoinding counting before the first event happens. */
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.triggerOn.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOn.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.triggerOn.value++
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOn.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOff.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value++
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOff.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.takePosition.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.takePosition.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.takePosition.value++
|
||||
tradingEngine.current.episode.distanceToEvent.takePosition.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.closePosition.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.closePosition.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.closePosition.value++
|
||||
tradingEngine.current.episode.distanceToEvent.closePosition.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.nextPhase.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.nextPhase.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.nextPhase.value++
|
||||
tradingEngine.current.episode.distanceToEvent.nextPhase.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.moveToPhase.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.moveToPhase.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.moveToPhase.value++
|
||||
tradingEngine.current.episode.distanceToEvent.moveToPhase.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.createOrder.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.createOrder.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.createOrder.value++
|
||||
tradingEngine.current.episode.distanceToEvent.createOrder.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.cancelOrder.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.cancelOrder.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.cancelOrder.value++
|
||||
tradingEngine.current.episode.distanceToEvent.cancelOrder.value++
|
||||
}
|
||||
|
||||
if (
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value > 0
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value > 0
|
||||
) {
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value++
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,10 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Episode'
|
||||
let thisObject = {
|
||||
mantain: mantain,
|
||||
openEpisode: openEpisode,
|
||||
closingEpisode: closingEpisode,
|
||||
updateExitType: updateExitType,
|
||||
closeEpisode: closeEpisode,
|
||||
updateEnds: updateEnds,
|
||||
resetTradingEngineDataStructure: resetTradingEngineDataStructure,
|
||||
updateCounters: updateCounters,
|
||||
updateStatistics: updateStatistics,
|
||||
calculateResults: calculateResults,
|
||||
calculateStatistics: calculateStatistics,
|
||||
initialize: initialize,
|
||||
@@ -35,25 +32,47 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
sessionParameters = undefined
|
||||
}
|
||||
|
||||
function openEpisode() {
|
||||
|
||||
/* Recording the opening at the Trading Engine Data Structure */
|
||||
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.candle.begin.value
|
||||
tradingEngine.current.episode.beginRate.value = tradingEngine.current.candle.close.value
|
||||
function mantain() {
|
||||
resetTradingEngineDataStructure()
|
||||
updateCounters()
|
||||
updateStatistics()
|
||||
updateEnds()
|
||||
}
|
||||
|
||||
function closingEpisode(exitType) {
|
||||
tradingEngine.current.episode.status.value = 'Closing'
|
||||
function openEpisode() {
|
||||
/*
|
||||
This function is called each time the simulation starts. That does not mean the Episode
|
||||
must be opened there, since it might happen that it is looping at the end of the market
|
||||
or the task / session was restarted.
|
||||
*/
|
||||
if (bot.FIRST_EXECUTION === true) {
|
||||
/* 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
|
||||
|
||||
/* The current balance is also the begin balance, that is how this starts. */
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value = sessionParameters.sessionBaseAsset.config.initialBalance
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value = sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
|
||||
/* Recording the opening at the Trading Engine Data Structure */
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
function updateExitType(exitType) {
|
||||
tradingEngine.current.episode.exitType.value = exitType
|
||||
}
|
||||
|
||||
function closeEpisode() {
|
||||
tradingEngine.current.episode.status.value = 'Closed'
|
||||
tradingEngine.current.episode.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.episode.endRate.value = tradingEngine.current.candle.close.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
|
||||
}
|
||||
|
||||
function resetEpisode() {
|
||||
@@ -62,8 +81,10 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
|
||||
function updateEnds() {
|
||||
if (tradingEngine.current.episode.status.value === 'Open') {
|
||||
tradingEngine.current.episode.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.episode.endRate.value = tradingEngine.current.candle.close.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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +113,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
|
||||
/* Updating Profit Loss */
|
||||
tradingEngine.current.episode.episodeStatistics.profitLoss.value =
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value +
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.episode.candle.close.value +
|
||||
tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value
|
||||
|
||||
tradingEngine.current.episode.episodeStatistics.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.profitLoss.value, 10)
|
||||
@@ -100,12 +121,12 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
/* Updating ROI */
|
||||
tradingEngine.current.episode.episodeStatistics.ROI.value =
|
||||
(
|
||||
sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value +
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value +
|
||||
sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.episode.candle.close.value +
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.episode.candle.close.value +
|
||||
sessionParameters.sessionQuotedAsset.config.initialBalance +
|
||||
tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value
|
||||
) / (
|
||||
sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value +
|
||||
sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.episode.candle.close.value +
|
||||
sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
) - 1
|
||||
|
||||
@@ -142,11 +163,11 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger) {
|
||||
|
||||
/* Updating Profit Loss */
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value =
|
||||
tradingEngine.current.balance.baseAsset.value -
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value -
|
||||
sessionParameters.sessionBaseAsset.config.initialBalance
|
||||
|
||||
tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value =
|
||||
tradingEngine.current.balance.quotedAsset.value -
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value -
|
||||
sessionParameters.sessionQuotedAsset.config.initialBalance
|
||||
|
||||
tradingEngine.current.episode.episodeBaseAsset.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.profitLoss.value, 10)
|
||||
|
||||
@@ -135,7 +135,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
}
|
||||
case 'Open': {
|
||||
/* Update this order properties */
|
||||
tradingEngineOrder.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngineOrder.end.value = tradingEngine.current.episode.candle.end.value
|
||||
tradingEngineOrder.orderCounters.periods.value++
|
||||
tradingEngineOrder.orderStatistics.days.value = tradingEngineOrder.orderCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
|
||||
@@ -191,13 +191,13 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngine.current.episode.episodeCounters.orders.value++
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.createOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.createOrder.value = 1
|
||||
|
||||
/* Create Order Procedure */
|
||||
tradingEngineOrder.status.value = 'Open'
|
||||
tradingEngineOrder.identifier.value = global.UNIQUE_ID()
|
||||
tradingEngineOrder.begin.value = tradingEngine.current.candle.begin.value
|
||||
tradingEngineOrder.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngineOrder.begin.value = tradingEngine.current.episode.candle.begin.value
|
||||
tradingEngineOrder.end.value = tradingEngine.current.episode.candle.end.value
|
||||
tradingEngineOrder.serialNumber.value = tradingEngine.current.episode.episodeCounters.orders.value
|
||||
tradingEngineOrder.orderName.value = tradingSystemOrder.name
|
||||
tradingEngineOrder.algorithmName.value = executionAlgorithm.name
|
||||
@@ -205,7 +205,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
|
||||
function calculateOrderRate() {
|
||||
/* 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
|
||||
tradingEngineOrder.rate.value = tradingEngine.current.episode.candle.close.value
|
||||
|
||||
/* Optional Rate Definition */
|
||||
if (tradingSystemOrder.orderRate !== undefined) {
|
||||
@@ -458,7 +458,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = 'Filled'
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,7 +515,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = 'Filled'
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
}
|
||||
if (order.remaining > 0 && order.status === AT_EXCHANGE_STATUS.CLOSED) {
|
||||
|
||||
@@ -524,7 +524,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = 'Closed at the Exchange'
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
}
|
||||
if (order.status === AT_EXCHANGE_STATUS.CANCELLED) {
|
||||
|
||||
@@ -533,7 +533,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = 'Cancelled at the Exchange'
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
}
|
||||
|
||||
syncWithExchange(tradingSystemOrder, tradingEngineOrder, order)
|
||||
@@ -657,24 +657,24 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
case tradingSystemOrder.type === 'Market Buy Order' || tradingSystemOrder.type === 'Limit Buy Order': {
|
||||
|
||||
/* Balance Base Asset: Undo the previous accounting */
|
||||
tradingEngine.current.balance.baseAsset.value =
|
||||
tradingEngine.current.balance.baseAsset.value -
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value -
|
||||
previousBaseAssetSizeFilled
|
||||
|
||||
/* Balance Base Asset: Account the current filling and fees */
|
||||
tradingEngine.current.balance.baseAsset.value =
|
||||
tradingEngine.current.balance.baseAsset.value +
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value +
|
||||
tradingEngineOrder.orderBaseAsset.sizeFilled.value
|
||||
|
||||
/* Balance Quoted Asset: Undo the previous accounting */
|
||||
tradingEngine.current.balance.quotedAsset.value =
|
||||
tradingEngine.current.balance.quotedAsset.value +
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value +
|
||||
previousQuotedAssetSizeFilled +
|
||||
previousQuotedAssetFeesPaid
|
||||
|
||||
/* Balance Quoted Asset: Account the current filling and fees */
|
||||
tradingEngine.current.balance.quotedAsset.value =
|
||||
tradingEngine.current.balance.quotedAsset.value -
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value -
|
||||
tradingEngineOrder.orderQuotedAsset.sizeFilled.value -
|
||||
tradingEngineOrder.orderQuotedAsset.feesPaid.value
|
||||
break
|
||||
@@ -682,31 +682,31 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
case tradingSystemOrder.type === 'Market Sell Order' || tradingSystemOrder.type === 'Limit Sell Order': {
|
||||
|
||||
/* Balance Base Asset: Undo the previous accounting */
|
||||
tradingEngine.current.balance.baseAsset.value =
|
||||
tradingEngine.current.balance.baseAsset.value +
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value +
|
||||
previousBaseAssetSizeFilled +
|
||||
previousBaseAssetFeesPaid
|
||||
|
||||
/* Balance Base Asset: Account the current filling and fees */
|
||||
tradingEngine.current.balance.baseAsset.value =
|
||||
tradingEngine.current.balance.baseAsset.value -
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value -
|
||||
tradingEngineOrder.orderBaseAsset.sizeFilled.value -
|
||||
tradingEngineOrder.orderBaseAsset.feesPaid.value
|
||||
|
||||
/* Balance Quoted Asset: Undo the previous accounting */
|
||||
tradingEngine.current.balance.quotedAsset.value =
|
||||
tradingEngine.current.balance.quotedAsset.value -
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value -
|
||||
previousQuotedAssetSizeFilled
|
||||
|
||||
/* Balance Quoted Asset: Account the current filling and fees */
|
||||
tradingEngine.current.balance.quotedAsset.value =
|
||||
tradingEngine.current.balance.quotedAsset.value +
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value =
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value +
|
||||
tradingEngineOrder.orderQuotedAsset.sizeFilled.value
|
||||
break
|
||||
}
|
||||
}
|
||||
tradingEngine.current.balance.baseAsset.value = global.PRECISE(tradingEngine.current.balance.baseAsset.value, 10)
|
||||
tradingEngine.current.balance.quotedAsset.value = global.PRECISE(tradingEngine.current.balance.quotedAsset.value, 10)
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.balance.value, 10)
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.balance.value, 10)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -734,7 +734,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = exitType
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
|
||||
recalculateStageSize(tradingEngineOrder)
|
||||
}
|
||||
@@ -765,7 +765,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
|
||||
tradingEngineOrder.exitType.value = exitType
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.closeOrder.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closeOrder.value = 1
|
||||
|
||||
/*
|
||||
Perhaps the order was filled a bit more between the last time we checked and when it was cancelled.
|
||||
|
||||
@@ -4,6 +4,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Position'
|
||||
let thisObject = {
|
||||
mantain: mantain,
|
||||
openPosition: openPosition,
|
||||
closingPosition: closingPosition,
|
||||
closePosition: closePosition,
|
||||
@@ -15,7 +16,6 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
updateEnds: updateEnds,
|
||||
resetTradingEngineDataStructure: resetTradingEngineDataStructure,
|
||||
updateCounters: updateCounters,
|
||||
resetPosition: resetPosition,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
@@ -38,14 +38,22 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
sessionParameters = undefined
|
||||
}
|
||||
|
||||
function mantain() {
|
||||
resetTradingEngineDataStructure()
|
||||
updateCounters()
|
||||
updateEnds()
|
||||
}
|
||||
|
||||
function openPosition(situationName) {
|
||||
|
||||
/* 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
|
||||
tradingEngine.current.position.identifier.value = global.UNIQUE_ID()
|
||||
tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value
|
||||
tradingEngine.current.position.beginRate.value = tradingEngine.current.candle.close.value
|
||||
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
|
||||
tradingEngine.current.position.situationName.value = situationName
|
||||
|
||||
/* Initializing Stop and Take Profit Stage / Phase */
|
||||
@@ -58,7 +66,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
tradingEngine.current.episode.episodeCounters.positions.value++
|
||||
|
||||
/* Inicializing this counter */
|
||||
tradingEngine.current.distanceToEvent.takePosition.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.takePosition.value = 1
|
||||
}
|
||||
|
||||
function closingPosition(exitType) {
|
||||
@@ -68,8 +76,10 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
|
||||
function closePosition() {
|
||||
tradingEngine.current.position.status.value = 'Closed'
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.position.endRate.value = tradingEngine.current.candle.close.value
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.episode.candle.end.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
|
||||
|
||||
/* Position Statistics & Results */
|
||||
updateStatistics()
|
||||
@@ -80,10 +90,6 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
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)
|
||||
}
|
||||
@@ -223,14 +229,16 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
|
||||
function updateEnds() {
|
||||
if (tradingEngine.current.position.status.value === 'Open') {
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.position.endRate.value = tradingEngine.current.candle.close.value
|
||||
tradingEngine.current.position.end.value = tradingEngine.current.episode.candle.end.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
|
||||
}
|
||||
}
|
||||
|
||||
function resetTradingEngineDataStructure() {
|
||||
if (tradingEngine.current.position.status.value === 'Closed') {
|
||||
resetPosition()
|
||||
tradingEngine.current.position.initialize(tradingEngine.current.position)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,12 +253,12 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
/* Profit Loss Calculation */
|
||||
tradingEngine.current.position.positionStatistics.profitLoss.value =
|
||||
(
|
||||
tradingEngine.current.balance.baseAsset.value * tradingEngine.current.position.endRate.value +
|
||||
tradingEngine.current.balance.quotedAsset.value
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value * tradingEngine.current.position.endRate.value +
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value
|
||||
) -
|
||||
(
|
||||
tradingEngine.previous.balance.baseAsset.value * tradingEngine.current.position.beginRate.value +
|
||||
tradingEngine.previous.balance.quotedAsset.value
|
||||
tradingEngine.current.position.positionBaseAsset.beginBalance * tradingEngine.current.position.beginRate.value +
|
||||
tradingEngine.current.position.positionQuotedAsset.beginBalance
|
||||
)
|
||||
tradingEngine.current.position.positionStatistics.profitLoss.value = global.PRECISE(tradingEngine.current.position.positionStatistics.profitLoss.value, 10)
|
||||
|
||||
@@ -261,8 +269,8 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
)
|
||||
* 100 /
|
||||
(
|
||||
tradingEngine.previous.balance.baseAsset.value * tradingEngine.current.position.beginRate.value +
|
||||
tradingEngine.previous.balance.quotedAsset.value
|
||||
tradingEngine.current.position.positionBaseAsset.beginBalance * tradingEngine.current.position.beginRate.value +
|
||||
tradingEngine.current.position.positionQuotedAsset.beginBalance
|
||||
)
|
||||
tradingEngine.current.position.positionStatistics.ROI.value = global.PRECISE(tradingEngine.current.position.positionStatistics.ROI.value, 10)
|
||||
|
||||
@@ -284,12 +292,12 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
|
||||
function updateResults() {
|
||||
/* Profit Loss Calculation */
|
||||
tradingEngine.current.position.positionBaseAsset.profitLoss.value =
|
||||
tradingEngine.current.balance.baseAsset.value -
|
||||
tradingEngine.previous.balance.baseAsset.value
|
||||
tradingEngine.current.episode.episodeBaseAsset.balance.value -
|
||||
tradingEngine.current.position.positionBaseAsset.beginBalance
|
||||
|
||||
tradingEngine.current.position.positionQuotedAsset.profitLoss.value =
|
||||
tradingEngine.current.balance.quotedAsset.value -
|
||||
tradingEngine.previous.balance.quotedAsset.value
|
||||
tradingEngine.current.episode.episodeQuotedAsset.balance.value -
|
||||
tradingEngine.current.position.positionQuotedAsset.beginBalance
|
||||
|
||||
tradingEngine.current.position.positionBaseAsset.profitLoss.value = global.PRECISE(tradingEngine.current.position.positionBaseAsset.profitLoss.value, 10)
|
||||
tradingEngine.current.position.positionQuotedAsset.profitLoss.value = global.PRECISE(tradingEngine.current.position.positionQuotedAsset.profitLoss.value, 10)
|
||||
|
||||
@@ -219,8 +219,8 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
of the day? Easy: the end of the candle must be 1 millisecod before the next day. That happens at any
|
||||
time frame.
|
||||
*/
|
||||
let currentDay = new Date(tradingEngine.current.candle.end.value)
|
||||
let nextDay = new Date(tradingEngine.current.candle.end.value + 1)
|
||||
let currentDay = new Date(tradingEngine.current.episode.candle.end.value)
|
||||
let nextDay = new Date(tradingEngine.current.episode.candle.end.value + 1)
|
||||
if (currentDay.getUTCDate() !== nextDay.getUTCDate()) {
|
||||
/*
|
||||
We will save the object only if it is closed, becasuse we are at the last candle of the day.
|
||||
@@ -302,7 +302,7 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
let recordProperty = product.record.properties[j]
|
||||
if (recordProperty.config.codeName === 'end') {
|
||||
let end = record[j]
|
||||
if (end >= tradingEngine.current.candle.end.value) {
|
||||
if (end >= tradingEngine.current.episode.candle.end.value) {
|
||||
outputFile.splice(i, 1)
|
||||
pruneOutputFile(product, outputFile)
|
||||
return
|
||||
|
||||
@@ -69,10 +69,10 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
let diff = lastBegin - firstBegin
|
||||
let amount = diff / sessionParameters.timeFrame.config.value
|
||||
|
||||
tradingEngine.current.candle.index.value = Math.trunc(amount) + 1 // Because we need to start from the next candle
|
||||
if (tradingEngine.current.candle.index.value < 0 || tradingEngine.current.candle.index.value > candles.length - 1) {
|
||||
tradingEngine.current.episode.candle.index.value = Math.trunc(amount) + 1 // Because we need to start from the next candle
|
||||
if (tradingEngine.current.episode.candle.index.value < 0 || tradingEngine.current.episode.candle.index.value > candles.length - 1) {
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> Cannot resume simulation.')
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> tradingEngine.current.candle.index.value = ' + tradingEngine.current.candle.index.value)
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> tradingEngine.current.episode.candle.index.value = ' + tradingEngine.current.episode.candle.index.value)
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> firstBegin = ' + firstBegin)
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> lastBegin = ' + lastBegin)
|
||||
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> diff = ' + diff)
|
||||
@@ -88,14 +88,14 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
let diff = targetEnd - firstEnd
|
||||
let amount = diff / sessionParameters.timeFrame.config.value
|
||||
|
||||
tradingEngine.current.candle.index.value = Math.trunc(amount)
|
||||
if (tradingEngine.current.candle.index.value < 0) { tradingEngine.current.candle.index.value = 0 }
|
||||
if (tradingEngine.current.candle.index.value > candles.length - 1) {
|
||||
tradingEngine.current.episode.candle.index.value = Math.trunc(amount)
|
||||
if (tradingEngine.current.episode.candle.index.value < 0) { tradingEngine.current.episode.candle.index.value = 0 }
|
||||
if (tradingEngine.current.episode.candle.index.value > candles.length - 1) {
|
||||
/*
|
||||
This will happen when the sessionParameters.timeRange.config.initialDatetime is beyond the last candle available,
|
||||
meaning that the dataSet needs to be updated with more up-to-date data.
|
||||
*/
|
||||
tradingEngine.current.candle.index.value = candles.length - 1
|
||||
tradingEngine.current.episode.candle.index.value = candles.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,8 +103,8 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
|
||||
async function loop() {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Processing candle # ' + tradingEngine.current.candle.index.value) }
|
||||
let candle = candles[tradingEngine.current.candle.index.value] // This is the current candle the Simulation is working at.
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Processing candle # ' + tradingEngine.current.episode.candle.index.value) }
|
||||
let candle = candles[tradingEngine.current.episode.candle.index.value] // This is the current candle the Simulation is working at.
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Candle Begin @ ' + (new Date(candle.begin)).toLocaleString()) }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Candle End @ ' + (new Date(candle.end)).toLocaleString()) }
|
||||
@@ -140,11 +140,11 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
/* Do the stuff needed previous to the run */
|
||||
tradingSystemModule.mantain()
|
||||
|
||||
/* Episode Counters and Statistics */
|
||||
tradingEpisodeModule.updateCounters()
|
||||
tradingEpisodeModule.updateStatistics()
|
||||
/* Episode Counters and Statistics update */
|
||||
tradingEpisodeModule.mantain()
|
||||
|
||||
tradingEngineModule.updateDistanceToEventsCounters()
|
||||
/* Run your maintaince procedure */
|
||||
tradingEngineModule.mantain()
|
||||
|
||||
/* Run one cycle of the Trading System*/
|
||||
await tradingSystemModule.run()
|
||||
@@ -157,23 +157,23 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
if (bot.STOP_SESSION === true) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this session.') }
|
||||
console.log('[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this session.')
|
||||
closeEpisode('Session Stopped')
|
||||
updateEpisode('Session Stopped')
|
||||
return
|
||||
}
|
||||
|
||||
if (global.STOP_TASK_GRACEFULLY === true) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this task.') }
|
||||
console.log('[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this task.')
|
||||
closeEpisode('Task Stopped')
|
||||
updateEpisode('Task Stopped')
|
||||
return
|
||||
}
|
||||
|
||||
if (tradingEngine.current.candle.index.value + 1 < candles.length) {
|
||||
if (tradingEngine.current.episode.candle.index.value + 1 < candles.length) {
|
||||
|
||||
/* Add new records to the process output */
|
||||
tradingRecordsModule.appendRecords()
|
||||
|
||||
tradingEngine.current.candle.index.value++
|
||||
tradingEngine.current.episode.candle.index.value++
|
||||
|
||||
setImmediate(loop) // This will execute the next loop in the next iteration of the NodeJs event loop allowing for other callbacks to be executed.
|
||||
} else {
|
||||
@@ -182,7 +182,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
|
||||
function closeEpisode(exitType) {
|
||||
tradingEpisodeModule.closingEpisode(exitType)
|
||||
tradingEpisodeModule.updateExitType(exitType)
|
||||
tradingEpisodeModule.closeEpisode()
|
||||
|
||||
/* Add new records to the process output */
|
||||
@@ -191,6 +191,15 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
afterLoop()
|
||||
}
|
||||
|
||||
function updateEpisode(exitType) {
|
||||
tradingEpisodeModule.updateExitType(exitType)
|
||||
|
||||
/* Add new records to the process output */
|
||||
tradingRecordsModule.appendRecords()
|
||||
|
||||
afterLoop()
|
||||
}
|
||||
|
||||
function afterLoop() {
|
||||
|
||||
tradingEngineModule.finalize()
|
||||
@@ -208,11 +217,11 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
|
||||
function heartBeat() {
|
||||
/* We will produce a simulation level heartbeat in order to inform the user this is running. */
|
||||
heartBeatDate = new Date(Math.trunc(tradingEngine.current.candle.begin.value / global.ONE_DAY_IN_MILISECONDS) * global.ONE_DAY_IN_MILISECONDS)
|
||||
heartBeatDate = new Date(Math.trunc(tradingEngine.current.episode.candle.begin.value / global.ONE_DAY_IN_MILISECONDS) * global.ONE_DAY_IN_MILISECONDS)
|
||||
if (heartBeatDate.valueOf() !== previousHeartBeatDate) {
|
||||
let processingDate = heartBeatDate.getUTCFullYear() + '-' + utilities.pad(heartBeatDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(heartBeatDate.getUTCDate(), 2)
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Simulation ' + bot.sessionKey + ' Loop # ' + tradingEngine.current.candle.index.value + ' @ ' + processingDate) }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Simulation ' + bot.sessionKey + ' Loop # ' + tradingEngine.current.episode.candle.index.value + ' @ ' + processingDate) }
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let fromDate = new Date(sessionParameters.timeRange.config.initialDatetime)
|
||||
@@ -305,15 +314,15 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
for (let i = 0; i < pArray.length; i++) {
|
||||
element = pArray[i]
|
||||
|
||||
if (tradingEngine.current.candle.end.value === element.end) { // when there is an exact match at the end we take that element
|
||||
if (tradingEngine.current.episode.candle.end.value === element.end) { // when there is an exact match at the end we take that element
|
||||
return element
|
||||
} else {
|
||||
if (
|
||||
i > 0 &&
|
||||
element.end > tradingEngine.current.candle.end.value
|
||||
element.end > tradingEngine.current.episode.candle.end.value
|
||||
) {
|
||||
let previousElement = pArray[i - 1]
|
||||
if (previousElement.end < tradingEngine.current.candle.end.value) {
|
||||
if (previousElement.end < tradingEngine.current.episode.candle.end.value) {
|
||||
return previousElement // If one elements goes into the future of currentCandle, then we stop and take the previous element.
|
||||
} else {
|
||||
return
|
||||
@@ -336,7 +345,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
*/
|
||||
if (bot.processingDailyFiles) { // We are processing Daily Files
|
||||
let candlesPerDay = global.ONE_DAY_IN_MILISECONDS / sessionParameters.timeFrame.config.value
|
||||
if (tradingEngine.current.candle.index.value === candles.length - 1) {
|
||||
if (tradingEngine.current.episode.candle.index.value === candles.length - 1) {
|
||||
if ((candles.length < candlesPerDay) || (candles.length > candlesPerDay && candles.length < candlesPerDay * 2)) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkLastCandle -> Skipping Candle because it is the last one and has not been closed yet.') }
|
||||
return false
|
||||
@@ -347,7 +356,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
}
|
||||
} else { // We are processing Market Files
|
||||
if (tradingEngine.current.candle.index.value === candles.length - 1) {
|
||||
if (tradingEngine.current.episode.candle.index.value === candles.length - 1) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkLastCandle -> Skipping Candle because it is the last one and has not been closed yet.') }
|
||||
return false
|
||||
}
|
||||
@@ -357,11 +366,11 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
|
||||
function checkInitialAndFinalDatetime() {
|
||||
/* Here we check that the current candle is not outside of user-defined time range at the session parameters.*/
|
||||
if (tradingEngine.current.candle.end.value < sessionParameters.timeRange.config.initialDatetime) {
|
||||
if (tradingEngine.current.episode.candle.end.value < sessionParameters.timeRange.config.initialDatetime) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkInitialAndFinalDatetime -> Skipping Candle before the sessionParameters.timeRange.config.initialDatetime.') }
|
||||
return false
|
||||
}
|
||||
if (tradingEngine.current.candle.begin.value > sessionParameters.timeRange.config.finalDatetime) {
|
||||
if (tradingEngine.current.episode.candle.begin.value > sessionParameters.timeRange.config.finalDatetime) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkInitialAndFinalDatetime -> Skipping Candle after the sessionParameters.timeRange.config.finalDatetime.') }
|
||||
return false
|
||||
}
|
||||
@@ -378,10 +387,10 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
because there the balances have shifted from their resting position.
|
||||
*/
|
||||
|
||||
let stopRunningDate = (new Date(tradingEngine.current.candle.begin.value)).toLocaleString()
|
||||
let stopRunningDate = (new Date(tradingEngine.current.episode.candle.begin.value)).toLocaleString()
|
||||
|
||||
if (sessionParameters.sessionBaseAsset.config.minimumBalance !== undefined) {
|
||||
if (tradingEngine.current.balance.baseAsset.value <= sessionParameters.sessionBaseAsset.config.minimumBalance) {
|
||||
if (tradingEngine.current.episode.episodeBaseAsset.balance.value <= sessionParameters.sessionBaseAsset.config.minimumBalance) {
|
||||
const errorMessage = 'Min Balance reached @ ' + stopRunningDate
|
||||
tradingSystem.errors.push([tradingSystem.id, errorMessage])
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[WARN] runSimulation -> checkMinimunAndMaximunBalance -> ' + errorMessage) }
|
||||
@@ -390,7 +399,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
|
||||
if (sessionParameters.sessionBaseAsset.config.maximumBalance !== undefined) {
|
||||
if (tradingEngine.current.balance.baseAsset.value >= sessionParameters.sessionBaseAsset.config.maximumBalance) {
|
||||
if (tradingEngine.current.episode.episodeBaseAsset.balance.value >= sessionParameters.sessionBaseAsset.config.maximumBalance) {
|
||||
const errorMessage = 'Max Balance reached @ ' + stopRunningDate
|
||||
tradingSystem.errors.push([tradingSystem.id, errorMessage])
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[WARN] runSimulation -> checkMinimunAndMaximunBalance -> ' + errorMessage) }
|
||||
@@ -399,7 +408,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
|
||||
if (sessionParameters.sessionQuotedAsset.config.minimumBalance !== undefined) {
|
||||
if (tradingEngine.current.balance.quotedAsset.value <= sessionParameters.sessionQuotedAsset.config.minimumBalance) {
|
||||
if (tradingEngine.current.episode.episodeQuotedAsset.balance.value <= sessionParameters.sessionQuotedAsset.config.minimumBalance) {
|
||||
const errorMessage = 'Min Balance reached @ ' + stopRunningDate
|
||||
tradingSystem.errors.push([tradingSystem.id, errorMessage])
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[WARN] runSimulation -> checkMinimunAndMaximunBalance -> ' + errorMessage) }
|
||||
@@ -408,7 +417,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
}
|
||||
|
||||
if (sessionParameters.sessionQuotedAsset.config.maximumBalance !== undefined) {
|
||||
if (tradingEngine.current.balance.quotedAsset.value >= sessionParameters.sessionQuotedAsset.config.maximumBalance) {
|
||||
if (tradingEngine.current.episode.episodeQuotedAsset.balance.value >= sessionParameters.sessionQuotedAsset.config.maximumBalance) {
|
||||
const errorMessage = 'Max Balance reached @ ' + stopRunningDate
|
||||
tradingSystem.errors.push([tradingSystem.id, errorMessage])
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[WARN] runSimulation -> checkMinimunAndMaximunBalance -> ' + errorMessage) }
|
||||
|
||||
@@ -14,7 +14,6 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
resetTradingEngineDataStructure: resetTradingEngineDataStructure,
|
||||
updateCounters: updateCounters,
|
||||
updateStatistics: updateStatistics,
|
||||
resetStage: resetStage,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
@@ -85,29 +84,17 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
}
|
||||
|
||||
function mantain() {
|
||||
mantainPositions()
|
||||
mantainStrategies()
|
||||
tradingPositionModule.mantain()
|
||||
tradingStrategyModule.mantain()
|
||||
mantainStages()
|
||||
mantainOrders()
|
||||
|
||||
function mantainStrategies() {
|
||||
tradingStrategyModule.resetTradingEngineDataStructure()
|
||||
tradingStrategyModule.updateCounters()
|
||||
tradingStrategyModule.updateEnds()
|
||||
}
|
||||
|
||||
function mantainStages() {
|
||||
resetTradingEngineDataStructure()
|
||||
updateCounters()
|
||||
updateEnds()
|
||||
}
|
||||
|
||||
function mantainPositions() {
|
||||
tradingPositionModule.resetTradingEngineDataStructure()
|
||||
tradingPositionModule.updateCounters()
|
||||
tradingPositionModule.updateEnds()
|
||||
}
|
||||
|
||||
function mantainOrders() {
|
||||
/* Reset All Exchange Orders that are on Closed status, to their initial value */
|
||||
if (tradingEngine.current.strategy.index.value === tradingEngine.current.strategy.index.config.initialValue) { return }
|
||||
@@ -209,7 +196,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
tradingStrategyModule.openStrategy(j, situation.name, strategy.name)
|
||||
|
||||
/* Initialize this */
|
||||
tradingEngine.current.distanceToEvent.triggerOn.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOn.value = 1
|
||||
|
||||
announcementsModule.makeAnnoucements(triggerStage.triggerOn)
|
||||
announcementsModule.makeAnnoucements(triggerStage)
|
||||
@@ -256,7 +243,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
tradingSystem.highlights.push(triggerStage.triggerOff.id)
|
||||
tradingSystem.highlights.push(triggerStage.id)
|
||||
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOff.value = 1
|
||||
announcementsModule.makeAnnoucements(triggerStage.triggerOff)
|
||||
changeStageStatus('Trigger Stage', 'Closed')
|
||||
tradingStrategyModule.closeStrategy('Trigger Off')
|
||||
@@ -343,8 +330,8 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
tradingSystem.evalFormulas(stageNode, 'Initial Definition')
|
||||
|
||||
/* Remember the balance we had before taking the position to later calculate profit or loss */
|
||||
tradingEngine.previous.balance.baseAsset.value = tradingEngine.current.balance.baseAsset.value
|
||||
tradingEngine.previous.balance.quotedAsset.value = tradingEngine.current.balance.quotedAsset.value
|
||||
tradingEngine.current.position.positionBaseAsset.beginBalance = tradingEngine.current.episode.episodeBaseAsset.balance.value
|
||||
tradingEngine.current.position.positionQuotedAsset.beginBalance = tradingEngine.current.episode.episodeQuotedAsset.balance.value
|
||||
|
||||
/* Entry Position size and rate */
|
||||
tradingSystem.evalFormulas(stageNode, 'Initial Targets')
|
||||
@@ -839,11 +826,11 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
if (
|
||||
(
|
||||
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Above' &&
|
||||
tradingEngine.current.candle.max.value >= tradingEngine.current.position.stopLoss.value
|
||||
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.stopLoss.value
|
||||
) ||
|
||||
(
|
||||
tradingEngine.current.position.stopLoss.stopLossPosition.value === 'Below' &&
|
||||
tradingEngine.current.candle.min.value <= tradingEngine.current.position.stopLoss.value
|
||||
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.stopLoss.value
|
||||
)
|
||||
) {
|
||||
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
|
||||
@@ -859,11 +846,11 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
if (
|
||||
(
|
||||
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Below' &&
|
||||
tradingEngine.current.candle.min.value <= tradingEngine.current.position.takeProfit.value
|
||||
tradingEngine.current.episode.candle.min.value <= tradingEngine.current.position.takeProfit.value
|
||||
) ||
|
||||
(
|
||||
tradingEngine.current.position.takeProfit.takeProfitPosition.value === 'Above' &&
|
||||
tradingEngine.current.candle.max.value >= tradingEngine.current.position.takeProfit.value
|
||||
tradingEngine.current.episode.candle.max.value >= tradingEngine.current.position.takeProfit.value
|
||||
)
|
||||
) {
|
||||
logger.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
|
||||
@@ -1023,8 +1010,8 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
tradingStrategyModule.closeStrategy('Position Closed')
|
||||
|
||||
/* Distance to Events Updates */
|
||||
tradingEngine.current.distanceToEvent.closePosition.value = 1
|
||||
tradingEngine.current.distanceToEvent.triggerOff.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.closePosition.value = 1
|
||||
tradingEngine.current.episode.distanceToEvent.triggerOff.value = 1
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1089,34 +1076,34 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
|
||||
function openStage(stage) {
|
||||
/* Recording the opening at the Trading Engine Data Structure */
|
||||
stage.begin.value = tradingEngine.current.candle.begin.value
|
||||
stage.beginRate.value = tradingEngine.current.candle.close.value
|
||||
stage.end.value = tradingEngine.current.candle.end.value
|
||||
stage.begin.value = tradingEngine.current.episode.candle.begin.value
|
||||
stage.beginRate.value = tradingEngine.current.episode.candle.close.value
|
||||
stage.end.value = tradingEngine.current.episode.candle.end.value
|
||||
}
|
||||
|
||||
function closeStage(stage) {
|
||||
/* Recording the closing at the Trading Engine Data Structure */
|
||||
stage.end.value = tradingEngine.current.candle.end.value
|
||||
stage.endRate.value = tradingEngine.current.candle.close.value
|
||||
stage.end.value = tradingEngine.current.episode.candle.end.value
|
||||
stage.endRate.value = tradingEngine.current.episode.candle.close.value
|
||||
}
|
||||
}
|
||||
|
||||
function resetStage(stage) {
|
||||
stage.initialize(stage)
|
||||
}
|
||||
|
||||
function updateEnds() {
|
||||
if (tradingEngine.current.strategyTriggerStage.status.value === 'Open') {
|
||||
tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.strategyTriggerStage.end.value = tradingEngine.current.episode.candle.end.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.candle.end.value
|
||||
tradingEngine.current.strategyOpenStage.end.value = tradingEngine.current.episode.candle.end.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.candle.end.value
|
||||
tradingEngine.current.strategyManageStage.end.value = tradingEngine.current.episode.candle.end.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.candle.end.value
|
||||
tradingEngine.current.strategyCloseStage.end.value = tradingEngine.current.episode.candle.end.value
|
||||
tradingEngine.current.strategyCloseStage.endRate.value = tradingEngine.current.episode.candle.close.value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,6 +1123,10 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
|
||||
resetStage(tradingEngine.current.strategyManageStage)
|
||||
resetStage(tradingEngine.current.strategyCloseStage)
|
||||
}
|
||||
|
||||
function resetStage(stage) {
|
||||
stage.initialize(stage)
|
||||
}
|
||||
}
|
||||
|
||||
function updateCounters() {
|
||||
|
||||
@@ -4,12 +4,9 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Strategy'
|
||||
let thisObject = {
|
||||
mantain: mantain,
|
||||
openStrategy: openStrategy,
|
||||
closeStrategy: closeStrategy,
|
||||
updateEnds: updateEnds,
|
||||
resetTradingEngineDataStructure: resetTradingEngineDataStructure,
|
||||
updateCounters: updateCounters,
|
||||
resetStrategy: resetStrategy,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
@@ -26,13 +23,19 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
|
||||
tradingEngine = undefined
|
||||
}
|
||||
|
||||
function mantain() {
|
||||
resetTradingEngineDataStructure()
|
||||
updateCounters()
|
||||
updateEnds()
|
||||
}
|
||||
|
||||
function openStrategy(index, situationName, strategyName) {
|
||||
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.candle.begin.value
|
||||
tradingEngine.current.strategy.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.strategy.beginRate.value = tradingEngine.current.candle.min.value
|
||||
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
|
||||
tradingEngine.current.strategy.situationName.value = situationName
|
||||
@@ -45,28 +48,24 @@ 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.candle.end.value
|
||||
tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.min.value
|
||||
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.end.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.
|
||||
*/
|
||||
tradingEngineModule.cloneValues(tradingEngine.current.strategy, tradingEngine.last.strategy)
|
||||
}
|
||||
|
||||
function resetStrategy() {
|
||||
tradingEngine.current.strategy.initialize(tradingEngine.current.strategy)
|
||||
}
|
||||
|
||||
function updateEnds() {
|
||||
if (tradingEngine.current.strategy.status.value === 'Open') {
|
||||
tradingEngine.current.strategy.end.value = tradingEngine.current.candle.end.value
|
||||
tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.close.value
|
||||
tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.end.value
|
||||
tradingEngine.current.strategy.endRate.value = tradingEngine.current.episode.candle.close.value
|
||||
}
|
||||
}
|
||||
|
||||
function resetTradingEngineDataStructure() {
|
||||
if (tradingEngine.current.strategy.status.value === 'Closed') {
|
||||
resetStrategy()
|
||||
tradingEngine.current.strategy.initialize(tradingEngine.current.strategy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user