Add: User-Defined-Code for Stages
This commit is contained in:
1 parent
3e8ca6a5ae
commit
35b852ff2a
9 files changed
+211
-16
No files matched your search
@@ -64,6 +64,12 @@
|
||||
"name": "announcements",
|
||||
"type": "array",
|
||||
"childType": "Announcement"
|
||||
},
|
||||
{
|
||||
"name": "userDefinedCode",
|
||||
"type": "node",
|
||||
"childType": "User Defined Code",
|
||||
"autoAdd": false
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "closeStage"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"code": "// Type you code"
|
||||
},
|
||||
"attachingRules": {
|
||||
"compatibleTypes": "->Condition->"
|
||||
"compatibleTypes": "->Condition->User Defined Code->"
|
||||
},
|
||||
"menuItems": [
|
||||
{
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
"name": "announcements",
|
||||
"type": "array",
|
||||
"childType": "Announcement"
|
||||
},
|
||||
{
|
||||
"name": "userDefinedCode",
|
||||
"type": "node",
|
||||
"childType": "User Defined Code",
|
||||
"autoAdd": false
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "manageStage"
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
"name": "announcements",
|
||||
"type": "array",
|
||||
"childType": "Announcement"
|
||||
},
|
||||
{
|
||||
"name": "userDefinedCode",
|
||||
"type": "node",
|
||||
"childType": "User Defined Code",
|
||||
"autoAdd": false
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "openStage"
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
"name": "announcements",
|
||||
"type": "array",
|
||||
"childType": "Announcement"
|
||||
},
|
||||
{
|
||||
"name": "userDefinedCode",
|
||||
"type": "node",
|
||||
"childType": "User Defined Code",
|
||||
"autoAdd": false
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "triggerStage"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"type": "User Defined Code",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Configure",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"propertyToCheckFor": "javascriptCode",
|
||||
"label": "Add Code",
|
||||
"relatedUiObject": "Javascript Code",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"actionFunction": "payload.executeAction",
|
||||
"label": "Delete",
|
||||
"iconPathOn": "delete-entity",
|
||||
"iconPathOff": "delete-entity"
|
||||
},
|
||||
{
|
||||
"action": "Copy Node Path",
|
||||
"label": "Copy Node Path",
|
||||
"iconPathOn": "copy-path",
|
||||
"iconPathOff": "copy-path",
|
||||
"actionFunction": "payload.executeAction"
|
||||
}
|
||||
],
|
||||
"addLeftIcons": true,
|
||||
"initialValues": {
|
||||
"config": "{ \n \"runWhenEnteringStage\": false, \n \"runWhenExitingStage\": false, \n \"runWhileAtStage\": false, \n \"WhileAtStage_whenToRun\": \"first|last\" \n}"
|
||||
},
|
||||
"editors": {
|
||||
"config": true
|
||||
},
|
||||
"level": 2,
|
||||
"attachingRules": {
|
||||
"compatibleTypes": "->Trigger Stage->Open Stage->Manage Stage->Close Stage->"
|
||||
},
|
||||
"childrenNodesProperties": [
|
||||
{
|
||||
"name": "javascriptCode",
|
||||
"type": "array",
|
||||
"childType": "Javascript Code",
|
||||
"autoAdd": true
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "userDefinedCode"
|
||||
}
|
||||
+78
-3
@@ -169,6 +169,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
|
||||
function checkTriggerOff() {
|
||||
if (tradingEngine.tradingCurrent.strategyTriggerStage.status.value === 'Open') {
|
||||
checkUserDefinedCode('Trigger Stage', 'Running', 'first');
|
||||
|
||||
let strategy = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value]
|
||||
let triggerStage = strategy.triggerStage
|
||||
@@ -246,6 +247,8 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
changeStageStatus('Trigger Stage', 'Closed', 'Position Taken')
|
||||
changeStageStatus('Open Stage', 'Opening')
|
||||
changeStageStatus('Manage Stage', 'Opening')
|
||||
} else {
|
||||
checkUserDefinedCode('Trigger Stage', 'Running', 'last');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,7 +302,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
tradingPositionModuleObject.initialTargets(tradingSystemStage, tradingEngineStage)
|
||||
initializeStageTargetSize()
|
||||
|
||||
/* From here on, the stage is officialy Open */
|
||||
/* From here on, the stage is officially Open */
|
||||
changeStageStatus('Open Stage', 'Open')
|
||||
}
|
||||
}
|
||||
@@ -311,6 +314,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
While the Open Stage is Open, we do our regular stuff: place orders and check
|
||||
what happened to the orders already placed.
|
||||
*/
|
||||
checkUserDefinedCode('Open Stage', 'Running', 'first');
|
||||
let tradingSystemStage = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].openStage
|
||||
let tradingEngineStage = tradingEngine.tradingCurrent.strategyOpenStage
|
||||
let executionNode = tradingSystemStage.openExecution
|
||||
@@ -324,6 +328,11 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
tradingEngineStage
|
||||
)
|
||||
checkIfStageNeedsToBeClosed(tradingEngineStage, tradingSystemStage, 'Open Stage')
|
||||
|
||||
/* User Defined Code if runWhileAtStage==true */
|
||||
if (tradingEngine.tradingCurrent.strategyOpenStage.status.value === 'Open') {
|
||||
checkUserDefinedCode('Open Stage', 'Running', 'last');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +419,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
if (tradingEngine.tradingCurrent.strategyManageStage.status.value === 'Opening') {
|
||||
let strategy = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value]
|
||||
let manageStage = strategy.manageStage
|
||||
|
||||
|
||||
/*
|
||||
The system allows the user not to define a Manage Stage, because the Manage Stage is optional.
|
||||
Here we are going to see if that is the case and if it is, we will inmidiatelly consider
|
||||
@@ -431,6 +440,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
function runWhenStatusIsOpen() {
|
||||
/* Open Status Procedure */
|
||||
if (tradingEngine.tradingCurrent.strategyManageStage.status.value === 'Open') {
|
||||
checkUserDefinedCode('Manage Stage', 'Running', 'first');
|
||||
let strategy = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value]
|
||||
let manageStage = strategy.manageStage
|
||||
|
||||
@@ -450,6 +460,11 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
|
||||
/* Checking if Stop or Take Profit were hit */
|
||||
checkStopLossOrTakeProfitWasHit()
|
||||
|
||||
/* If User Defined Code exists check for runWhileAtStage */
|
||||
if (tradingEngine.tradingCurrent.strategyManageStage.status.value === 'Open') {
|
||||
checkUserDefinedCode('Manage Stage', 'Running', 'last');
|
||||
}
|
||||
}
|
||||
|
||||
function calculateStopLoss() {
|
||||
@@ -846,6 +861,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
/*
|
||||
This will happen as long as the Close Stage is Open.
|
||||
*/
|
||||
checkUserDefinedCode('Close Stage', 'Running', 'first');
|
||||
let tradingSystemStage = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].closeStage
|
||||
let tradingEngineStage = tradingEngine.tradingCurrent.strategyCloseStage
|
||||
let executionNode = tradingSystemStage.closeExecution
|
||||
@@ -859,6 +875,10 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
)
|
||||
|
||||
checkIfStageNeedsToBeClosed(tradingEngineStage, tradingSystemStage, 'Close Stage')
|
||||
/* If User Defined Code exists check for runWhileAtStage */
|
||||
if (tradingEngine.tradingCurrent.strategyCloseStage.status.value === 'Open') {
|
||||
checkUserDefinedCode('Close Stage', 'Running', 'last');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,9 +1142,11 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
}
|
||||
if (stage.status.value === 'Open') {
|
||||
openStage(stage)
|
||||
checkUserDefinedCode(stageName, 'Open')
|
||||
}
|
||||
if (stage.status.value === 'Closed') {
|
||||
closeStage(stage)
|
||||
checkUserDefinedCode(stageName, 'Closed')
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1228,4 +1250,57 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
|
||||
}
|
||||
throw 'Error Already Recorded'
|
||||
}
|
||||
}
|
||||
|
||||
/* checkUserDefinedCode(): Checks if User Defined Code exists and processes if applicable. */
|
||||
function checkUserDefinedCode(stage, status, when) {
|
||||
let tradingSystemStage = getTradingSystemStage(stage);
|
||||
|
||||
if (tradingSystemStage.userDefinedCode !== undefined) {
|
||||
if (status === 'Running' && when !== tradingSystemStage.userDefinedCode.config.WhileAtStage_whenToRun) { return; }
|
||||
|
||||
switch(status) {
|
||||
case 'Open' : {
|
||||
if (tradingSystemStage.userDefinedCode.config.runWhenEnteringStage) {
|
||||
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Running' : {
|
||||
if (tradingSystemStage.userDefinedCode.config.runWhileAtStage &&
|
||||
tradingSystemStage.userDefinedCode.config.WhileAtStage_whenToRun === when) {
|
||||
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Closed' : {
|
||||
if (tradingSystemStage.userDefinedCode.config.runWhenExitingStage) {
|
||||
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* getTradingSystemStage(): takes stage name returns stage object. */
|
||||
function getTradingSystemStage(stage) {
|
||||
switch(stage) {
|
||||
case 'Trigger Stage' : {
|
||||
return tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].triggerStage;
|
||||
break;
|
||||
}
|
||||
case 'Open Stage' : {
|
||||
return tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].openStage;
|
||||
break;
|
||||
}
|
||||
case 'Manage Stage' : {
|
||||
return tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].manageStage;
|
||||
break
|
||||
}
|
||||
case 'Close Stage' : {
|
||||
return tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].closeStage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-10
@@ -13,7 +13,7 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
These 3 are the main data structures available to users
|
||||
when writing conditions and formulas.
|
||||
*/
|
||||
@@ -74,6 +74,10 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
evalNode(startingNode, 'Formulas', descendentOfNodeType)
|
||||
}
|
||||
|
||||
tradingSystem.evalUserCode = function (startingNode, descendentOfNodeType) {
|
||||
evalNode(startingNode, 'User Codes', descendentOfNodeType);
|
||||
}
|
||||
|
||||
tradingSystem.addError = function (errorDataArray) {
|
||||
/*
|
||||
This function adds to the array of error info a rate.
|
||||
@@ -87,7 +91,7 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
|
||||
tradingSystem.addWarning = function (warningDataArray) {
|
||||
/*
|
||||
This function adds to the array of warning info a rate.
|
||||
This function adds to the array of warning info a rate.
|
||||
This rate will later help plotting the warning at the
|
||||
charts.
|
||||
*/
|
||||
@@ -98,7 +102,7 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
|
||||
tradingSystem.addInfo = function (infoDataArray) {
|
||||
/*
|
||||
This function adds to the array of warning info a rate.
|
||||
This function adds to the array of warning info a rate.
|
||||
This rate will later help plotting the warning at the
|
||||
charts.
|
||||
*/
|
||||
@@ -108,9 +112,9 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
}
|
||||
|
||||
function isItInside(elementWithTimestamp, elementWithBeginEnd) {
|
||||
/*
|
||||
The function is to allow in Conditions and Formulas to easily
|
||||
know when an element with timestamp (like the ones of
|
||||
/*
|
||||
The function is to allow in Conditions and Formulas to easily
|
||||
know when an element with timestamp (like the ones of
|
||||
single files) are inside the time range
|
||||
of an element with a time range, like a candle.
|
||||
*/
|
||||
@@ -167,8 +171,8 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
}
|
||||
|
||||
function updateChart(pChart, pExchange, pMarket) {
|
||||
/*
|
||||
We need these 3 data structures to be a local objects
|
||||
/*
|
||||
We need these 3 data structures to be a local objects
|
||||
accessible while evaluating conditions and formulas.
|
||||
*/
|
||||
chart = pChart
|
||||
@@ -216,7 +220,7 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
tradingStagesModuleObject.cycleBasedStatistics()
|
||||
|
||||
} catch (err) {
|
||||
/*
|
||||
/*
|
||||
If an error ocurred during execution, it was alreeady logged and
|
||||
included at the errors array. That means we need to do nothing here,
|
||||
just prevent the execution to be halted for not handling exceptions.
|
||||
@@ -258,6 +262,15 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we check if there is a User Defined-Javascript Code to be evaluated: */
|
||||
if (node.type === 'Javascript Code' && evaluating === 'User Codes') {
|
||||
if (node.code !== undefined) {
|
||||
if (isDescendent === true) {
|
||||
evalJSCode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we go down through all this node children */
|
||||
let schemaDocument = TS.projects.superalgos.globals.taskConstants.APP_SCHEMA_MAP.get(node.project + '-' + node.type)
|
||||
if (schemaDocument === undefined) { return }
|
||||
@@ -395,5 +408,31 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) {
|
||||
|
||||
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] evalFormula -> value = ' + value)
|
||||
}
|
||||
}
|
||||
|
||||
function evalJSCode(node) {
|
||||
let value
|
||||
let errorMessage
|
||||
let docs
|
||||
|
||||
try {
|
||||
value = eval(node.code);
|
||||
|
||||
} catch (err) {
|
||||
value = 0
|
||||
errorMessage = err.message
|
||||
docs = {
|
||||
project: 'Superalgos',
|
||||
category: 'Topic',
|
||||
type: 'TS LF Trading Bot Error - Evaluating User Code Error',
|
||||
placeholder: {}
|
||||
}
|
||||
TS.projects.superalgos.utilities.docsFunctions.buildPlaceholder(docs, err, node.name, node.code, undefined)
|
||||
}
|
||||
|
||||
if (errorMessage !== undefined) {
|
||||
tradingSystem.addError([node.id, errorMessage, docs])
|
||||
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] evalFormula -> errorMessage = ' + errorMessage)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,8 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() {
|
||||
'Size In Base Asset->Size In Quoted Asset->Position Rate->Formula->' +
|
||||
'Situation->Condition->Javascript Code->' +
|
||||
'Market Order->Limit Order->' +
|
||||
'Simulated Exchange Events->Simulated Partial Fill->Simulated Actual Rate->Simulated Fees Paid->Formula->'
|
||||
'Simulated Exchange Events->Simulated Partial Fill->Simulated Actual Rate->Simulated Fees Paid->Formula->' +
|
||||
'User Defined Code->Javascript Code->'
|
||||
|
||||
let tradingSystem = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node.tradingSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath)
|
||||
|
||||
@@ -145,7 +146,8 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() {
|
||||
'Begin->End->Exit Type->Status->Begin Rate->End Rate->Stage Base Asset->Stage Quoted Asset->Size Placed->Target Size->Size Filled->Fees Paid->Stage Defined In->' +
|
||||
'Serial Number->Identifier->Begin->End->Begin Rate->End Rate->Strategy Name->Status->Exit Type->' +
|
||||
'Balance->Begin Balance->End Balance->' +
|
||||
'Index->Situation Name->Formula->Periods->'
|
||||
'Index->Situation Name->Formula->Periods->' +
|
||||
'User Variables->User Defined Variable->'
|
||||
|
||||
let tradingEngine = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node.tradingEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath)
|
||||
|
||||
|
||||
Reference in new issue
Block a user