Files
Superalgos/TaskServer/LowFrequencyTrading/TradingOutput.js
T
2020-12-01 17:33:35 +01:00

234 lines
12 KiB
JavaScript

exports.newTradingOutput = function (processIndex, tradingEngineModule, FILE_STORAGE) {
/*
This module will load if necesary all the data outputs so that they can be appended with new
records if needed. After running the simulation, it will save all the data outputs.
*/
const MODULE_NAME = 'Trading Output'
let thisObject = {
initialize: initialize,
finalize: finalize,
start: start
}
let fileStorage = FILE_STORAGE.newFileStorage(processIndex)
return thisObject
function finalize() {
thisObject = undefined
utilities = undefined
fileStorage = undefined
commons = undefined
}
function initialize() {
}
async function start(chart, timeFrame, timeFrameLabel, tradingProcessDate) {
try {
if (timeFrame > TS.projects.superalgos.globals.timeFrames.dailyFilePeriods()[0][0]) {
TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES = false
} else {
TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES = true
}
/* Preparing everything for the Simulation */
const TRADING_SIMULATION = require('./TradingSimulation.js')
let tradingSimulation = TRADING_SIMULATION.newTradingSimulation(processIndex, tradingEngineModule)
let outputDatasets = TS.projects.superalgos.utilities.nodeFunctions.nodeBranchToArray(TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
let outputDatasetsMap = new Map()
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES === true) {
/*
For Daily Files, we are going to initialize the outputs at the first execution
if we are not resuming, but also at every following execution except when
we are at the head of the market, because at the head of the market we need to
append more data to the same output files that already exists.
*/
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_FIRST_LOOP === true && TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_RESUMING === false) {
await initializeOutputs()
} else {
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.tradingEngine.current.episode.headOfTheMarket.value === true) {
await readFiles()
} else {
await initializeOutputs()
}
}
} else {
/*
Form Market Files, we are only going to initialize the outputs at the first run
and if we are not resuming execution. Subsequent runs means that we are at the
head of the market. Remember that backtests finishes the session once the reach
the final datetime.
*/
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_FIRST_LOOP === true && TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_RESUMING === false) {
await initializeOutputs()
} else {
await readFiles()
}
}
await tradingSimulation.runSimulation(
chart,
outputDatasetsMap,
writeFiles
)
tradingSimulation.finalize()
return
async function initializeOutputs() {
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES) {
await initializeDailyFiles()
} else {
await initializeMarketFiles()
}
}
async function initializeDailyFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Daily Files') {
outputDatasetsMap.set(dataset.parentNode.config.codeName, [])
}
}
}
async function initializeMarketFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Market Files') {
outputDatasetsMap.set(dataset.parentNode.config.codeName, [])
}
}
}
async function readFiles() {
/*
This bot have an output of files that it generates. At every call to the bot, it needs to read the previously generated
files in order to later append more information after the execution is over. Here in this function we are going to
read those output files and get them ready for appending content during the simulation.
*/
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES) {
await readDailyFiles()
} else {
await readMarketFiles()
}
}
async function readMarketFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Market Files') {
let fileName = 'Data.json'
let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + '/Output/' + TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_FOLDER_NAME + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
await readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
}
}
async function readDailyFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Daily Files') {
let dateForPath = tradingProcessDate.getUTCFullYear() + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(tradingProcessDate.getUTCMonth() + 1, 2) + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(tradingProcessDate.getUTCDate(), 2);
let fileName = 'Data.json'
let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + '/Output/' + TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_FOLDER_NAME + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
await readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
}
}
async function readOutputFile(fileName, filePath, productName) {
filePath += '/' + fileName
let response = await fileStorage.asyncGetTextFile(filePath, true)
if (response.err.message === 'File does not exist.') {
outputDatasetsMap.set(productName, [])
return
}
if (response.err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
throw(response.err)
}
outputDatasetsMap.set(productName, JSON.parse(response.text))
}
async function writeFiles() {
/*
The output of files which were appended with information during the simulation execution, now needs to be saved.
*/
if (TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES) {
await writeDailyFiles()
} else {
await writeMarketFiles()
}
}
async function writeMarketFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Market Files') {
let fileName = 'Data.json'
let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + '/Output/' + TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_FOLDER_NAME + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
await writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
}
}
async function writeDailyFiles() {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let dataset = outputDatasetNode.referenceParent
if (dataset.config.type === 'Daily Files') {
let dateForPath = tradingProcessDate.getUTCFullYear() + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(tradingProcessDate.getUTCMonth() + 1, 2) + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(tradingProcessDate.getUTCDate(), 2);
let fileName = 'Data.json'
let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + '/Output/' + TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_FOLDER_NAME + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
await writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
}
}
async function writeOutputFile(fileName, filePath, productName) {
filePath += '/' + fileName
let fileContent = JSON.stringify(outputDatasetsMap.get(productName))
let response = await fileStorage.asyncCreateTextFile(filePath, fileContent)
if (response.err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
throw(response.err)
}
}
} catch (err) {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE.write(MODULE_NAME, '[ERROR] start -> err = ' + err.stack)
throw(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE)
}
}
}