Snaphost re implemented

This commit is contained in:
Luis Fernando Molina committed 2020-06-28 15:29:00 +02:00
1 parent b35bade968
commit e0f95a32d0
4 files changed
+176 -73

No files matched your search

+157 -62
View File
@@ -5,7 +5,10 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
const MODULE_NAME = 'Snapshots'
let thisObject = {
manageSnapshots: manageSnapshots,
strategyEntry: strategyEntry,
strategyExit: strategyExit,
positionEntry: positionEntry,
positionExit: positionExit,
addCodeToSnapshot: addCodeToSnapshot,
initialize: initialize,
finalize: finalize
@@ -13,6 +16,7 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
let tradingEngine
let tradingSystem
let sessionParameters
const SNAPSHOTS_FOLDER_NAME = 'Snapshots'
@@ -20,90 +24,153 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
let triggerOnSnapshot
let takePositionSnapshot
/* Snapshots of Trigger On and Take Positions */
/* Snapshots of Strategies and Positions */
let snapshots = {
headers: undefined,
triggerOn: [],
takePosition: [],
lastTriggerOn: undefined,
lastTakePosition: undefined
headers: [],
strategies: [],
positions: []
}
/* We are going to take snapshots of the values of indicators at key moments of the sumulation. */
let snapshotKeys = new Map()
snapshotLoopHeaders = []
snapshotDataRecord = []
saveAsLastTriggerOnSnapshot = false
saveAsLastTakePositionSnapshot = false
addToSnapshots = false
let snapshotKeys = new Map() // This is to prevent adding the same indicator / variable to the output collection.
let createHeaders = true // This is going to be true only once
let createCloseHeaders = true // This is going to be true only once
let closeValues
let strategyValues
let addToStrategyValues
let positionValues
let addToPositionValues
return thisObject
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
tradingSystem = bot.simulationState.tradingSystem
sessionParameters = bot.SESSION.parameters
}
function finalize() {
tradingEngine = undefined
tradingSystem = undefined
sessionParameters = undefined
}
function manageSnapshots() {
return // TODO enable this to run
/* Snapshots Management (before we generate the trade record and delete that info) */
if (saveAsLastTriggerOnSnapshot === true) {
snapshots.lastTriggerOn = snapshotDataRecord
saveAsLastTriggerOnSnapshot = false
function strategyEntry() {
/*
We will record here a snapshot of all values used in conditions and formulas within the Trading System.
If the strategy exists with a trade, this information will be added to the snapshots file.
*/
strategyValues = []
addToStrategyValues = true
evalNode(tradingSystem)
/* Turn off this */
createHeaders = false
addToStrategyValues = false
}
function strategyExit() {
getResults()
let valuesArray = closeValues.concat(strategyValues)
snapshots.strategies.push(valuesArray)
}
function positionEntry() {
positionValues = []
addToPositionValues = true
evalNode(tradingSystem)
/* Turn off this */
createHeaders = false
addToPositionValues = false
}
function positionExit() {
getResults()
let valuesArray = closeValues.concat(positionValues)
snapshots.positions.push(valuesArray)
}
function evalNode(node) {
if (node === undefined) { return }
/* Here we check if there is a codition to be evaluated */
if (node.type === 'Condition') {
/* We will eval this condition */
evalCondition(node)
}
if (saveAsLastTakePositionSnapshot === true) {
snapshots.lastTakePosition = snapshotDataRecord
saveAsLastTakePositionSnapshot = false
}
if (addToSnapshots === true) {
let closeValues = [
tradingEngine.episode.episodeCounters.positions.value, // Position Number
(new Date(tradingEngine.current.candle.begin.value)).toISOString(), // Datetime
tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value].name, // Strategy Name
tradingEngine.current.strategy.situationName.value, // Trigger On Situation
tradingEngine.current.position.situationName.value, // Take Position Situation
hitOrFial(), // Result
tradingEngine.last.position.positionStatistics.ROI.value, // ROI
exitType() // Exit Type
]
function hitOrFial() {
if (tradingEngine.last.position.positionStatistics.ROI.value > 0) { return 'HIT' } else { return 'FAIL' }
/* Here we check if there is a formula to be evaluated */
if (node.type === 'Formula') {
if (node.code !== undefined) {
/* We will eval this formula */
evalFormula(node)
}
}
function exitType() {
switch (tradingEngine.current.position.exitType.value) {
case 1: return 'Stop'
case 2: return 'Take Profit'
/* Now we go down through all this node children */
let nodeDefinition = bot.APP_SCHEMA_MAP.get(node.type)
if (nodeDefinition === undefined) { return }
if (nodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < nodeDefinition.properties.length; i++) {
let property = nodeDefinition.properties[i]
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
if (node[property.name] !== undefined) {
evalNode(node[property.name])
}
previousPropertyName = property.name
}
break
}
case 'array': {
if (node[property.name] !== undefined) {
let nodePropertyArray = node[property.name]
for (let m = 0; m < nodePropertyArray.length; m++) {
evalNode(nodePropertyArray[m])
}
}
break
}
}
}
snapshots.triggerOn.push(closeValues.concat(snapshots.lastTriggerOn))
snapshots.takePosition.push(closeValues.concat(snapshots.lastTakePosition))
snapshots.lastTriggerOn = undefined
snapshots.lastTakePosition = undefined
addToSnapshots = false
}
let closeHeaders = ['Trade Number', 'Close Datetime', 'Strategy', 'Trigger On Situation', 'Take Position Situation', 'Result', 'ROI', 'Exit Type']
if (snapshots.headers === undefined) {
snapshots.headers = closeHeaders.concat(JSON.parse(JSON.stringify(snapshotLoopHeaders)))
}
}
function addCodeToSnapshot(code) {
if (code === undefined) { return }
function evalCondition(node) {
/*
The code can be at the condition node if it was done with the Conditions Editor, or it can also be
at a Javascript Code node. If there is a Javascript object we will give it preference and take the code
from there. Otherwise we will take the code from the Condition node.
*/
let nodeWithCode = node
if (node.javascriptCode !== undefined) {
if (node.javascriptCode.code !== undefined) {
nodeWithCode = node.javascriptCode
}
}
addCodeToSnapshot(nodeWithCode)
}
function evalFormula(node) {
let nodeWithCode = node
addCodeToSnapshot(nodeWithCode)
}
function addCodeToSnapshot(nodeWithCode) {
if (nodeWithCode === undefined) { return }
if (nodeWithCode.code === undefined) { return }
try {
let instructionsArray = code.split(' ')
let instructionsArray = nodeWithCode.code.split(' ')
for (let i = 0; i < instructionsArray.length; i++) {
let instruction = instructionsArray[i]
instruction = instruction.replace('(', '')
@@ -133,7 +200,7 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
}
// Example: chart.at01hs.popularSMA.sma200 - chart.at01hs.popularSMA.sma100 < 10
if (timeFrame !== 'atAnyvariable.timeFrame') {
if (timeFrame !== 'atAnyTimeFrame') {
timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7)
}
let key = timeFrame + '-' + product + '-' + property
@@ -141,17 +208,45 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
if (existingKey === undefined) { // means that at the current loop this property of this product was not used before.
snapshotKeys.set(key, key)
snapshotLoopHeaders.push(key)
if (createHeaders === true) {
snapshots.headers.push(key)
}
let value = eval(instruction)
snapshotDataRecord.push(value)
if (addToStrategyValues === true) {
strategyValues.push(value)
}
if (addToPositionValues === true) {
positionValues.push(value)
}
}
}
}
} catch (err) {
logger.write(MODULE_NAME, '[ERROR] runSimulation -> addCodeToSnapshot -> code = ' + code)
tradingSystem.errors.push(nodeWithCode.id, err.message)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> addCodeToSnapshot -> nodeWithCode.code = ' + nodeWithCode.code)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> addCodeToSnapshot -> err = ' + err.stack)
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
}
}
function getResults() {
let closeHeaders = ['Trade Number', 'Close Datetime', 'Strategy Name', 'Trigger On Situation', 'Take Position Situation', 'Result', 'ROI', 'Exit Type']
closeValues = [
tradingEngine.episode.episodeCounters.positions.value, // Position Number
(new Date(tradingEngine.current.candle.begin.value)).toISOString(), // Datetime
tradingEngine.last.strategy.strategyName.value, // Strategy Name
tradingEngine.last.strategy.situationName.value, // Trigger On Situation
tradingEngine.last.position.situationName.value, // Take Position Situation
tradingEngine.last.position.positionStatistics.hitFail.value, // Result
tradingEngine.last.position.positionStatistics.ROI.value, // ROI
tradingEngine.last.position.exitType.value // Exit Type
]
if (createCloseHeaders === true) {
snapshots.headers = closeHeaders.concat(JSON.parse(JSON.stringify(snapshots.headers)))
}
}
}
+5
View File
@@ -188,5 +188,10 @@ exports.newTradingPosition = function newTradingPosition(bot, logger) {
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'
}
}
}
-7
View File
@@ -64,10 +64,6 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
let tradingRecordsModule = TRADING_RECORDS_MODULE.newTradingRecords(bot, logger)
tradingRecordsModule.initialize(outputDatasetsMap)
const SNAPSHOTS_MODULE = require('./Snapshots.js')
let snapshotsModule = SNAPSHOTS_MODULE.newSnapshots(bot, logger)
snapshotsModule.initialize()
const TRADING_SYSTEM_MODULE = require('./TradingSystem.js')
let tradingSystemModule = TRADING_SYSTEM_MODULE.newTradingSystem(bot, logger)
tradingSystemModule.initialize()
@@ -217,8 +213,6 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
/* After a position was closed, we need to close the strategy. */
tradingSystemModule.exitStrategyAfterPosition()
snapshotsModule.manageSnapshots()
tradingRecordsModule.appendRecords()
controlLoop()
@@ -253,7 +247,6 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
tradingExecutionModule.finalize()
tradingSystemModule.finalize()
tradingRecordsModule.finalize()
snapshotsModule.finalize()
callback()
}
+14 -4
View File
@@ -47,6 +47,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
const ANNOUNCEMENTS_MODULE = require('./Announcements.js')
let announcementsModule = ANNOUNCEMENTS_MODULE.newAnnouncements(bot, logger)
const SNAPSHOTS_MODULE = require('./Snapshots.js')
let snapshotsModule = SNAPSHOTS_MODULE.newSnapshots(bot, logger)
return thisObject
function initialize() {
@@ -57,6 +60,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
tradingStrategyModule.initialize()
tradingPositionModule.initialize()
announcementsModule.initialize()
snapshotsModule.initialize()
}
function finalize() {
@@ -69,6 +73,9 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
announcementsModule.finalize()
announcementsModule = undefined
snapshotsModule.finalize()
snapshotsModule = undefined
chart = undefined
conditions = undefined
@@ -130,7 +137,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
/* Here we check if there is a formula to be evaluated */
if (node.type === 'Formula' && evaluating === 'Formulas') {
if (node.code !== undefined) {
/* We will eval this condition */
/* We will eval this formula */
evalFormula(node)
}
}
@@ -307,9 +314,12 @@ exports.newTradingSystem = function newTradingSystem(bot, logger) {
announcementsModule.makeAnnoucements(triggerStage.triggerOn)
announcementsModule.makeAnnoucements(triggerStage)
/* TODO See what to do with this:
saveAsLastTriggerOnSnapshot = true
*/
if (sessionParameters.snapshots !== undefined) {
if (sessionParameters.snapshots.config.strategy === true) {
snapshotsModule.strategyEntry()
}
}
logger.write(MODULE_NAME, '[INFO] checkTriggerOn -> Entering into Strategy: ' + strategy.name)
return true // This Means that we have just met the conditions to trigger on.