Snaphost re implemented
This commit is contained in:
1 parent
b35bade968
commit
e0f95a32d0
4 files changed
+176
-73
No files matched your search
@@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in new issue
Block a user