Files
Superalgos/LowFrequencyTrading/TradingRecords.js
T
2020-06-15 16:15:01 +02:00

138 lines
6.0 KiB
JavaScript

exports.newTradingRecords = function newTradingRecords(bot, logger) {
const MODULE_NAME = 'Trading Records'
let thisObject = {
appendRecords: appendRecords,
initialize: initialize,
finalize: finalize
}
let tradingEngine
let tradingSystem
let outputDatasetsMap
return thisObject
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.
}
function finalize() {
tradingEngine = undefined
tradingSystem = undefined
outputDatasetsMap = undefined
}
function appendRecords() {
/*
Here we add records to the output files. At the product config property nodePath
we have a pointer to the node that have the information we need to extract.
Later, based on the product record definition we will extract each individual value.
*/
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
let product = dataset.parentNode
let record
let outputDatasetArray = outputDatasetsMap.get(product.config.codeName)
if (bot.processingDailyFiles === true && dataset.config.type === 'Daily Files') {
record = scanRecordDefinition(product)
outputDatasetArray.push(record)
}
if (bot.processingDailyFiles === false && dataset.config.type === 'Market Files') {
record = scanRecordDefinition(product)
outputDatasetArray.push(record)
}
}
function scanRecordDefinition(product) {
/*
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.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) {
propertyRootNode = eval(recordProperty.config.nodePath)
}
/*
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 + '"'
}
if (recordProperty.config.decimals !== undefined) {
value = Number(value.toFixed(recordProperty.config.decimals))
}
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
}
}