Fixed Transaction Records
This commit is contained in:
1 parent
83d54fefe2
commit
5e6f946f60
6 files changed
+87
-35
No files matched your search
@@ -45,7 +45,7 @@ exports.newAnnouncements = function newAnnouncements(bot, logger) {
|
||||
}
|
||||
}
|
||||
|
||||
if (tradingEngine.episode.episodeCounters.periods > lastPeriodAnnounced) {
|
||||
if (tradingEngine.episode.episodeCounters.periods.value > lastPeriodAnnounced) {
|
||||
if (isNaN(value) === false) {
|
||||
/* The Value Variation is what tells us how much the value already announced must change in order to annouce it again. */
|
||||
let valueVariation
|
||||
@@ -72,12 +72,12 @@ exports.newAnnouncements = function newAnnouncements(bot, logger) {
|
||||
|
||||
/* Next, we will remmeber this announcement was already done, so that it is not announced again in further processing of the same day. */
|
||||
if (newAnnouncementRecord.periods !== undefined) {
|
||||
newAnnouncementRecord.periods = tradingEngine.episode.episodeCounters.periods
|
||||
newAnnouncementRecord.periods = tradingEngine.episode.episodeCounters.periods.value
|
||||
newAnnouncementRecord.value = value
|
||||
} else {
|
||||
newAnnouncementRecord = {
|
||||
key: key,
|
||||
periods: tradingEngine.episode.episodeCounters.periods,
|
||||
periods: tradingEngine.episode.episodeCounters.periods.value,
|
||||
value: value
|
||||
}
|
||||
variable.announcements.push(newAnnouncementRecord)
|
||||
|
||||
@@ -133,8 +133,8 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
}
|
||||
|
||||
function updateEpisodeCountersAndStatistics() {
|
||||
tradingEngine.episode.episodeCounters.periods++
|
||||
tradingEngine.episode.episodeStatistics.days = tradingEngine.episode.episodeCounters.periods * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
tradingEngine.episode.episodeCounters.periods.value++
|
||||
tradingEngine.episode.episodeStatistics.days.value = tradingEngine.episode.episodeCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
|
||||
function updatePositionCountersAndStatistics() {
|
||||
@@ -278,11 +278,11 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
if (sessionParameters.sessionBaseAsset.name === bot.market.marketBaseAsset) {
|
||||
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.positionCounters.positions.value
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days * 365
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days.value * 365
|
||||
} else {
|
||||
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.positionCounters.positions.value
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days * 365
|
||||
tradingEngine.episode.episodeStatistics.anualizedRateOfReturn.value = tradingEngine.episode.episodeStatistics.ROI.value / tradingEngine.episode.episodeStatistics.days.value * 365
|
||||
}
|
||||
|
||||
addRecords()
|
||||
|
||||
@@ -105,7 +105,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
/* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */
|
||||
if (variable.executionContext !== undefined) {
|
||||
if (variable.executionContext.periods !== undefined) {
|
||||
if (tradingEngine.episode.episodeCounters.periods <= variable.executionContext.periods) {
|
||||
if (tradingEngine.episode.episodeCounters.periods.value <= variable.executionContext.periods) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution.') }
|
||||
takePositionAtSimulation()
|
||||
return
|
||||
@@ -149,7 +149,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
|
||||
variable.executionContext = {
|
||||
status: 'Taking Position',
|
||||
periods: tradingEngine.episode.episodeCounters.periods
|
||||
periods: tradingEngine.episode.episodeCounters.periods.value
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putOpeningOrder -> Ready to create order.') }
|
||||
@@ -164,7 +164,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putOpeningOrder -> onOrderCreated -> DEFAULT_OK_RESPONSE ') }
|
||||
variable.executionContext = {
|
||||
status: 'In a Position',
|
||||
periods: tradingEngine.episode.episodeCounters.periods,
|
||||
periods: tradingEngine.episode.episodeCounters.periods.value,
|
||||
amountA: amountA,
|
||||
amountB: amountB,
|
||||
orderId: order.id
|
||||
@@ -244,7 +244,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
/* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */
|
||||
if (variable.executionContext !== undefined) {
|
||||
if (variable.executionContext.periods !== undefined) {
|
||||
if (tradingEngine.episode.episodeCounters.periods <= variable.executionContext.periods) {
|
||||
if (tradingEngine.episode.episodeCounters.periods.value <= variable.executionContext.periods) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putClosingOrder -> Exiting function because this closing was already submited at a previous execution.') }
|
||||
closePositionAtSimulation()
|
||||
return
|
||||
@@ -275,7 +275,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
|
||||
variable.executionContext = {
|
||||
status: 'Closing Position',
|
||||
periods: tradingEngine.episode.episodeCounters.periods
|
||||
periods: tradingEngine.episode.episodeCounters.periods.value
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putClosingOrder -> About to close position at the exchange.') }
|
||||
@@ -290,7 +290,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> putClosingOrder -> onOrderCreated -> DEFAULT_OK_RESPONSE ') }
|
||||
variable.executionContext = {
|
||||
status: 'Position Closed',
|
||||
periods: tradingEngine.episode.episodeCounters.periods,
|
||||
periods: tradingEngine.episode.episodeCounters.periods.value,
|
||||
amountA: amountA,
|
||||
amountB: amountB,
|
||||
orderId: order.id
|
||||
|
||||
@@ -83,7 +83,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, UTILITIES, FIL
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
|
||||
|
||||
readOutputFile(fileName, filePath, dataset.parentNode.config.pluralVariableName)
|
||||
readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, UTILITIES, FIL
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
|
||||
|
||||
readOutputFile(fileName, filePath, dataset.parentNode.config.pluralVariableName)
|
||||
readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, UTILITIES, FIL
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
|
||||
|
||||
writeOutputFile(fileName, filePath, dataset.parentNode.config.pluralVariableName)
|
||||
writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, UTILITIES, FIL
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
|
||||
|
||||
writeOutputFile(fileName, filePath, dataset.parentNode.config.pluralVariableName)
|
||||
writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize(pOutputDatasets, pOutputDatasetsMap) {
|
||||
function initialize(pOutputDatasetsMap) {
|
||||
tradingEngine = bot.simulationState.tradingEngine
|
||||
tradingSystem = bot.simulationState.tradingSystem
|
||||
outputDatasetsMap = pOutputDatasetsMap // These are the files turned into arrays, stored in a Map by Product codeName.
|
||||
@@ -52,32 +52,84 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
|
||||
}
|
||||
|
||||
function scanRecordDefinition(product) {
|
||||
let rootNode = eval(product.config.nodePath)
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
let productRootNode = eval(product.config.nodePath)
|
||||
let record = []
|
||||
for (let j = 0; j < product.recordDefinition.recordProperties.length; j++) {
|
||||
let recordProperty = product.recordDefinition.recordProperties[j]
|
||||
let value
|
||||
for (let j = 0; j < product.record.properties.length; j++) {
|
||||
let recordProperty = product.record.properties[j]
|
||||
/*
|
||||
The Property Root Node is the Root of the Hiriarchy branch we must find in order
|
||||
to get the node where we are going to extract the value. Initially
|
||||
we point it to the Product Root Node, because that is the default in case
|
||||
a property does not have at its configuration a different nodePath configured
|
||||
pointing to an specific Root for the property.
|
||||
*/
|
||||
let propertyRootNode = productRootNode
|
||||
/*
|
||||
If we find at the configuration a nodePath, then we take this path to find
|
||||
the Root Node specifically for this property only.
|
||||
*/
|
||||
if (recordProperty.config.nodePath !== undefined) {
|
||||
let childNode = rootNode[recordProperty.config.childNode]
|
||||
if (recordProperty.config.index !== undefined) {
|
||||
value = childNode[recordProperty.config.codeName] // this returns an array
|
||||
value = value[recordProperty.config.index].value // this return a node item of the array and its value
|
||||
} else {
|
||||
value = childNode[recordProperty.config.codeName].value // here we get the value of the childNode
|
||||
}
|
||||
} else {
|
||||
value = rootNode[recordProperty.config.codeName].value // this is the standard way
|
||||
propertyRootNode = eval(recordProperty.config.nodePath)
|
||||
}
|
||||
if (value === Infinity) {
|
||||
value = Number.MAX_SAFE_INTEGER
|
||||
/*
|
||||
The Target Node is the node from where we are going to exctract the value.
|
||||
We will use the codeName of the Record Property to match it with
|
||||
the any of the properties of the Root Node to get the Target Node.
|
||||
*/
|
||||
let targetNode = propertyRootNode[recordProperty.config.codeName]
|
||||
/*
|
||||
If the codeName of the Record Property can not match the name of the property at
|
||||
the target node, the user can explicitly specify the property name at the configuration,
|
||||
and in those cases we need to use that. This happens when there are many Record Properties
|
||||
pointing to the same property at the Target Node.
|
||||
*/
|
||||
if (recordProperty.config.childProperty !== undefined) {
|
||||
targetNode = propertyRootNode[recordProperty.config.childProperty]
|
||||
}
|
||||
/*
|
||||
It can happen that intead of having a Node in targetNode what we have is an
|
||||
array of nodes. We need to pick one of the elements of the array and for that
|
||||
we use the Index value we find at the configuration of the Record Property.
|
||||
*/
|
||||
if (recordProperty.config.index !== undefined) {
|
||||
targetNode = targetNode[recordProperty.config.index]
|
||||
}
|
||||
/*
|
||||
By Default the value is extracted from the value property of the Target Node.
|
||||
But it might happen the the Target Node does not exist for example when there is an Array
|
||||
of Nodes defined in the Record Properties but not all of them exist at the Root Node.
|
||||
We filter out those cases by not extracting the value from the value property.
|
||||
*/
|
||||
let value
|
||||
if (targetNode !== undefined) {
|
||||
value = targetNode.value
|
||||
}
|
||||
|
||||
value = safeValue(value)
|
||||
if (recordProperty.config.isString === true) {
|
||||
value = '"' + value + '"'
|
||||
}
|
||||
record.push(value)
|
||||
}
|
||||
|
||||
return record
|
||||
}
|
||||
}
|
||||
|
||||
function safeValue(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 === Infinity) {
|
||||
value = Number.MAX_SAFE_INTEGER
|
||||
}
|
||||
if (value === undefined) {
|
||||
value = 0
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -233,7 +233,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
|
||||
|
||||
snapshotsModule.manageSnapshots()
|
||||
tradingRecordsModule.appendRecords()
|
||||
annoucementsModule.makeAnnoucements() // After everything at the simulation level was done, we will do the annoucements that are pending.
|
||||
announcementsModule.makeAnnoucements() // After everything at the simulation level was done, we will do the annoucements that are pending.
|
||||
|
||||
controlLoop()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user