Merge branch 'develop' of https://github.com/Superalgos/Superalgos into develop
This commit is contained in:
commit
3082c64484
351 files changed
+65893
-19636
No files matched your search
@@ -2,9 +2,14 @@ name: Publish Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, develop]
|
||||
release:
|
||||
types: [published, created, edited]
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- created
|
||||
- edited
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
|
||||
@@ -1,38 +1,16 @@
|
||||
name: Build/release Binaries
|
||||
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
#release:
|
||||
# types: [published, created]
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download a file
|
||||
run: curl "https://raw.githubusercontent.com/${{ github.repository }}/master/package.json" -o package.json
|
||||
|
||||
- name: get-version
|
||||
id: version
|
||||
uses: nyaa8/package-version@v1
|
||||
with:
|
||||
path: './package.json'
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: viperproject/create-nightly-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.PACKAGE_VERSION }}
|
||||
release_name: Superalgos-v${{ env.PACKAGE_VERSION }}
|
||||
|
||||
build-release:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: create-release
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
@@ -40,19 +18,15 @@ jobs:
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: develop
|
||||
|
||||
- name: Install Node.js, NPM and Yarn
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: get-version
|
||||
id: version
|
||||
uses: nyaa8/package-version@v1
|
||||
with:
|
||||
path: './package.json'
|
||||
|
||||
- name: Get version
|
||||
id: vars
|
||||
run: echo "::set-output name=tag::$(node -p "require('./package.json').version")"
|
||||
|
||||
- name: Build/release Electron app
|
||||
uses: samuelmeuli/action-electron-builder@v1
|
||||
@@ -60,10 +34,6 @@ jobs:
|
||||
# GitHub token, automatically provided to the action
|
||||
# (No need to define this secret in the repo settings)
|
||||
github_token: ${{ secrets.github_token }}
|
||||
args: "-c.extraMetadata.version=${{ env.PACKAGE_VERSION }} -c build/electron-builder.json -p always"
|
||||
|
||||
# If the commit is tagged with a version (e.g. "v1.0.0"),
|
||||
# release the app after building
|
||||
# release: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
args: "-c.extraMetadata.version=${{ steps.vars.outputs.tag }} -c build/electron-builder.json -p always"
|
||||
release: true
|
||||
|
||||
@@ -17,11 +17,9 @@ jobs:
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y%m%d')"
|
||||
|
||||
- name: get-version
|
||||
id: version
|
||||
uses: nyaa8/package-version@v1
|
||||
with:
|
||||
path: './package.json'
|
||||
- name: Get version
|
||||
id: vars
|
||||
run: echo "::set-output name=tag::$(node -p "require('./package.json').version")"
|
||||
|
||||
- name: Create nightly release
|
||||
id: create_release
|
||||
@@ -29,8 +27,8 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.PACKAGE_VERSION }}.${{ steps.date.outputs.date }}
|
||||
release_name: Superalgos ${{ env.PACKAGE_VERSION }} Snapshot ${{ steps.date.outputs.date }}
|
||||
tag_name: ${{ steps.vars.outputs.tag }}.${{ steps.date.outputs.date }}
|
||||
release_name: Superalgos-Beta-v${{ steps.vars.outputs.tag }} Snapshot ${{ steps.date.outputs.date }}
|
||||
keep_num: 5
|
||||
keep_tags: false
|
||||
|
||||
@@ -39,7 +37,7 @@ jobs:
|
||||
needs: create-release
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
os: [windows-latest, macos-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: Get current date
|
||||
@@ -56,11 +54,9 @@ jobs:
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: get-version
|
||||
id: version
|
||||
uses: nyaa8/package-version@v1
|
||||
with:
|
||||
path: './package.json'
|
||||
- name: Get version
|
||||
id: vars
|
||||
run: echo "::set-output name=tag::$(node -p "require('./package.json').version")"
|
||||
|
||||
- name: Build/release Electron app
|
||||
uses: samuelmeuli/action-electron-builder@v1
|
||||
@@ -68,7 +64,7 @@ jobs:
|
||||
# GitHub token, automatically provided to the action
|
||||
# (No need to define this secret in the repo settings)
|
||||
github_token: ${{ secrets.github_token }}
|
||||
args: "-c.extraMetadata.main=electron-wrapper.js -c.extraMetadata.version=${{ env.PACKAGE_VERSION }}.${{ steps.date.outputs.date }} -c build/electron-builder.json -p onTagOrDraft"
|
||||
args: "-c.extraMetadata.version=${{ steps.vars.outputs.tag }}.${{ steps.date.outputs.date }} -c build/electron-builder.json -p onTagOrDraft"
|
||||
|
||||
# If the commit is tagged with a version (e.g. "v1.0.0"),
|
||||
# release the app after building
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "C:\\Superalgos"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"search.maintainFileSearchCache": true
|
||||
}
|
||||
}
|
||||
+52
-109
@@ -1,126 +1,69 @@
|
||||
exports.newDesktopApp = function newDesktopApp() {
|
||||
|
||||
let thisObject = {
|
||||
userProfiles: undefined,
|
||||
p2pNetworkClient: undefined,
|
||||
p2pNetwork: undefined,
|
||||
p2pNetworkPeers: undefined,
|
||||
webSocketsClient: undefined,
|
||||
webSocketsInterface: undefined,
|
||||
socialGraph: undefined,
|
||||
run: run
|
||||
}
|
||||
|
||||
DK.desktopApp = thisObject
|
||||
|
||||
return thisObject
|
||||
|
||||
async function run() {
|
||||
/*
|
||||
Here we will store our running objects:
|
||||
*/
|
||||
DK.running = {}
|
||||
/*
|
||||
This is the Personal Social Graph for the user running this App.
|
||||
*/
|
||||
DK.running.socialGraph = DK.projects.socialTrading.modules.socialGraph.newSocialTradingModulesSocialGraph()
|
||||
await DK.running.socialGraph.initialize()
|
||||
/*
|
||||
This is the Web Sockets client that interacts with the Superalgos Network.
|
||||
*/
|
||||
DK.running.webSocketsClient = SA.projects.network.modules.webSocketsAppClient.newNetworkModulesWebSocketsAppClient()
|
||||
await DK.running.webSocketsClient.initialize()
|
||||
console.log('Desktop Client Connected to Network Node via Web Sockets ................... Connected to port ' + global.env.NETWORK_WEB_SOCKETS_INTERFACE_PORT)
|
||||
|
||||
/* These are the Network Interfaces by which the Web App interacts with this Desktop Client.*/
|
||||
await setupNetwork()
|
||||
await setupServices()
|
||||
|
||||
DK.running.webSocketsInterface = DK.projects.socialTrading.modules.webSocketsInterface.newDesktopModulesWebSocketsInterface()
|
||||
DK.running.webSocketsInterface.initialize()
|
||||
console.log('Desktop Client Web Sockets Interface ....................................... Listening at port ' + global.env.DESKTOP_WEB_SOCKETS_INTERFACE_PORT)
|
||||
|
||||
|
||||
DK.running.httpInterface = DK.projects.socialTrading.modules.httpInterface.newDesktopModulesHttpInterface()
|
||||
DK.running.httpInterface.initialize()
|
||||
console.log('Desktop Client Http Interface .............................................. Listening at port ' + global.env.DESKTOP_HTTP_INTERFACE_PORT)
|
||||
|
||||
return
|
||||
|
||||
let queryMessage
|
||||
let query
|
||||
/*
|
||||
Test Query User Profiles.
|
||||
*/
|
||||
queryMessage = {
|
||||
queryType: SA.projects.socialTrading.globals.queryTypes.USER_PROFILES,
|
||||
emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId,
|
||||
initialIndex: 'Last',
|
||||
amountRequested: 10,
|
||||
direction: 'Past'
|
||||
async function setupNetwork() {
|
||||
/*
|
||||
We set up ourselves as a Network Client.
|
||||
*/
|
||||
thisObject.p2pNetworkClient = SA.projects.network.modules.p2pNetworkClient.newNetworkModulesP2PNetworkClient()
|
||||
await thisObject.p2pNetworkClient.initialize()
|
||||
/*
|
||||
We will read all user profiles plugins and get from there our network identity.
|
||||
*/
|
||||
thisObject.userProfiles = SA.projects.network.modules.userProfiles.newNetworkModulesUserProfiles()
|
||||
await thisObject.userProfiles.initialize(global.env.DESKTOP_APP_SIGNING_ACCOUNT, thisObject.p2pNetworkClient)
|
||||
/*
|
||||
We set up the P2P Network.
|
||||
*/
|
||||
thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork()
|
||||
await thisObject.p2pNetwork.initialize('Network Client')
|
||||
/*
|
||||
Set up the connections to network nodes.
|
||||
*/
|
||||
thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers()
|
||||
await thisObject.p2pNetworkPeers.initialize(
|
||||
'Network Client',
|
||||
thisObject.p2pNetworkClient,
|
||||
thisObject.p2pNetwork,
|
||||
global.env.DESKTOP_APP_MAX_OUTGOING_PEERS
|
||||
)
|
||||
}
|
||||
|
||||
query = {
|
||||
requestType: 'Query',
|
||||
queryMessage: JSON.stringify(queryMessage)
|
||||
}
|
||||
async function setupServices() {
|
||||
/*
|
||||
This is the Personal Social Graph for the user running this App.
|
||||
*/
|
||||
thisObject.socialGraph = DK.projects.socialTrading.modules.socialGraph.newSocialTradingModulesSocialGraph()
|
||||
await thisObject.socialGraph.initialize()
|
||||
/*
|
||||
These are the Network Interfaces by which the Web App interacts with this Desktop Client.
|
||||
*/
|
||||
thisObject.webSocketsInterface = DK.projects.socialTrading.modules.webSocketsInterface.newDesktopModulesWebSocketsInterface()
|
||||
thisObject.webSocketsInterface.initialize()
|
||||
console.log('Desktop Client Web Sockets Interface ......................................... Listening at port ' + JSON.parse(DK.desktopApp.p2pNetworkClient.node.config).webSocketsPort)
|
||||
|
||||
await DK.webSocketsClient.sendMessage(
|
||||
JSON.stringify(query)
|
||||
)
|
||||
.then(showProfiles)
|
||||
.catch(onError)
|
||||
|
||||
async function showProfiles(profiles) {
|
||||
console.log(profiles)
|
||||
|
||||
for (let i = 0; i < profiles.length; i++) {
|
||||
let profile = profiles[i]
|
||||
|
||||
/*
|
||||
Test Following Profiles.
|
||||
*/
|
||||
let eventMessage = {
|
||||
eventId: SA.projects.foundations.utilities.miscellaneousFunctions.genereteUniqueId(),
|
||||
eventType: SA.projects.socialTrading.globals.eventTypes.FOLLOW_USER_PROFILE,
|
||||
emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId,
|
||||
targetUserProfileId: profile.userProfileId
|
||||
}
|
||||
|
||||
let event = {
|
||||
requestType: 'Event',
|
||||
eventMessage: JSON.stringify(eventMessage)
|
||||
}
|
||||
|
||||
await DK.webSocketsClient.sendMessage(
|
||||
JSON.stringify(event)
|
||||
)
|
||||
.then(followAdded)
|
||||
.catch(onError)
|
||||
|
||||
function followAdded() {
|
||||
console.log("User Profile " + profile.userProfileHandle + " followed.")
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Test Query User Profile Stats.
|
||||
*/
|
||||
queryMessage = {
|
||||
queryType: SA.projects.socialTrading.globals.queryTypes.USER_PROFILE_STATS,
|
||||
emitterUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId,
|
||||
targetUserProfileId: SA.secrets.map.get(global.env.DESKTOP_APP_SIGNING_ACCOUNT).userProfileId
|
||||
}
|
||||
|
||||
query = {
|
||||
requestType: 'Query',
|
||||
queryMessage: JSON.stringify(queryMessage)
|
||||
}
|
||||
|
||||
await DK.webSocketsClient.sendMessage(
|
||||
JSON.stringify(query)
|
||||
)
|
||||
.then(showProfilesStats)
|
||||
.catch(onError)
|
||||
|
||||
function showProfilesStats(profile) {
|
||||
console.log(profile)
|
||||
}
|
||||
|
||||
/*
|
||||
Error Handling
|
||||
*/
|
||||
function onError(errorMessage) {
|
||||
console.log('[ERROR] Query not executed. ' + errorMessage)
|
||||
thisObject.httpInterface = DK.projects.socialTrading.modules.httpInterface.newDesktopModulesHttpInterface()
|
||||
thisObject.httpInterface.initialize()
|
||||
console.log('Desktop Client Http Interface ................................................ Listening at port ' + JSON.parse(DK.desktopApp.p2pNetworkClient.node.config).webPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
/* Root object*/
|
||||
/* Root objects*/
|
||||
let UI = {
|
||||
projects: {},
|
||||
schemas: { projectSchema: undefined },
|
||||
environment: undefined,
|
||||
clientNode: undefined,
|
||||
running: {}
|
||||
}
|
||||
|
||||
@@ -13,3 +14,4 @@ We will use this to load functions originally intended for Nodejs
|
||||
*/
|
||||
let exports = {}
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ function loadSuperalgos() {
|
||||
|
||||
function onResponse(err, file) {
|
||||
UI.environment = JSON.parse(file)
|
||||
setupClientNode()
|
||||
}
|
||||
}
|
||||
|
||||
function setupClientNode() {
|
||||
httpRequest(undefined, 'ClientNode', onResponse)
|
||||
|
||||
function onResponse(err, file) {
|
||||
UI.clientNode = JSON.parse(file)
|
||||
setupProjectsSchema()
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -10,7 +10,7 @@ exports.newDesktopRoot = function newDesktopRoot() {
|
||||
|
||||
return thisObject
|
||||
|
||||
async function run() {
|
||||
async function run(debugSettings) {
|
||||
/*
|
||||
The DK object is accessible everywhere at the Superalgos Desktop App.
|
||||
It provides access to all modules built for this App.
|
||||
@@ -25,6 +25,10 @@ exports.newDesktopRoot = function newDesktopRoot() {
|
||||
let ENVIRONMENT = require('./Environment.js');
|
||||
let ENVIRONMENT_MODULE = ENVIRONMENT.newEnvironment()
|
||||
global.env = ENVIRONMENT_MODULE
|
||||
|
||||
if (debugSettings !== undefined && debugSettings.DESKTOP_APP_SIGNING_ACCOUNT !== undefined) {
|
||||
global.env.DESKTOP_APP_SIGNING_ACCOUNT = debugSettings.DESKTOP_APP_SIGNING_ACCOUNT
|
||||
}
|
||||
/*
|
||||
First thing is to load the project schema file.
|
||||
*/
|
||||
|
||||
+8
-8
@@ -16,9 +16,9 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
This walkthrough is broken up into to parts: a quick-start guide to running [Superalgos](https://github.com/Superalgos/Superalgos) with Docker and a deeper, more theoretical dive into containers with the hopes of explaining some of the design decisions.
|
||||
This walk through is broken up into to parts: a quick-start guide to running [Superalgos](https://github.com/Superalgos/Superalgos) with Docker and a deeper, more theoretical dive into containers with the hopes of explaining some of the design decisions.
|
||||
|
||||
[Superalgos](https://github.com/Superalgos/Superalgos), at its core, is a web application which also means it can be deployed inside a container like many other web applications. One of the leading platforms for operating containers is Docker. Docker can run on many different operatng systems and compute platforms. The containers provide an easy, fast, repeatable, and secure way to deploy and distribute applications. While it doesn't take much experience to run containers or Docker, there are some basics that any user should learn in order to use the technology effectively.
|
||||
[Superalgos](https://github.com/Superalgos/Superalgos), at its core, is a web application which also means it can be deployed inside a container like many other web applications. One of the leading platforms for operating containers is Docker. Docker can run on many different operating systems and compute platforms. The containers provide an easy, fast, repeatable, and secure way to deploy and distribute applications. While it doesn't take much experience to run containers or Docker, there are some basics that any user should learn in order to use the technology effectively.
|
||||
|
||||
Before getting started, be aware that Docker is not the originally intended method of running the [Superalgos](https://github.com/Superalgos/Superalgos) application and as such there are some drawbacks to doing so. Namely, you won't be able contribute back to the project or configure your Governance profile. We'll discuss this more later. Therefore, you should only consider using the Docker container for production deployments.
|
||||
|
||||
@@ -55,7 +55,7 @@ Docker should automatically start after installation. If you don't see the whale
|
||||
|
||||
### Linux and BSD
|
||||
|
||||
On Linux and BSD systems, Docker can be installed using the prefered package manager. [Step by step instructions for many different distributions](https://docs.docker.com/engine/install/debian/) of Linux can be found in the official Docker Docs. Since [Superalgos](https://github.com/Superalgos/Superalgos) runs well on Raspberry Pi 4 single-board computers, I'm going to illustrate the commands necessary to run [Superalgos](https://github.com/Superalgos/Superalgos) on the Raspbian Linux distribution.
|
||||
On Linux and BSD systems, Docker can be installed using the preferred package manager. [Step by step instructions for many different distributions](https://docs.docker.com/engine/install/debian/) of Linux can be found in the official Docker Docs. Since [Superalgos](https://github.com/Superalgos/Superalgos) runs well on Raspberry Pi 4 single-board computers, I'm going to illustrate the commands necessary to run [Superalgos](https://github.com/Superalgos/Superalgos) on the Raspbian Linux distribution.
|
||||
|
||||
```shell
|
||||
# install the requirements
|
||||
@@ -70,7 +70,7 @@ sudo apt-get install \
|
||||
# add the gpg keys to verify the packages
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
|
||||
# confgure the official repository
|
||||
# configure the official repository
|
||||
echo \
|
||||
"deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
@@ -84,7 +84,7 @@ Docker should automatically start when it is done installing. You can check its
|
||||
|
||||
## Running Superalgos
|
||||
|
||||
Now that we have Docker installed and running, we can run the container. The option `--rm` will remove the isntance of the container when it is exited.
|
||||
Now that we have Docker installed and running, we can run the container. The option `--rm` will remove the instance of the container when it is exited.
|
||||
|
||||
```shell
|
||||
docker run --rm ghcr.io/superalgos/superalgos:latest
|
||||
@@ -147,7 +147,7 @@ Continue reading the [Docker Command Line documentation](https://docs.docker.com
|
||||
|
||||
### Using Docker-Compose
|
||||
|
||||
Docker-compose is a wrapper for the Docker API which makes it a little easier to maintain a declaritive configuration for an application instead of using the direct command line commands. There is a sample docker-compose configuration included in the [Superalgos](https://github.com/Superalgos/Superalgos) which you can as the basis for your own configuration.
|
||||
Docker-compose is a wrapper for the Docker API which makes it a little easier to maintain a declarative configuration for an application instead of using the direct command line commands. There is a sample docker-compose configuration included in the [Superalgos](https://github.com/Superalgos/Superalgos) which you can as the basis for your own configuration.
|
||||
|
||||
Let's download the sample and edit it. If you don't use `vim`, change that command for your preferred editor.
|
||||
|
||||
@@ -236,10 +236,10 @@ Docker has many advantages which can aid in every step from development through
|
||||
Docker maintains a list of [Dockerfile best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) in their main documentation. These tips dictate many of the decisions around the Superalgos Dockerfile. Some of the tips that are used by [Superalgos](https://github.com/Superalgos/Superalgos) are listed below.
|
||||
|
||||
- Use `.dockerignore` to prevent unwanted data from entering the container. This keeps the container small but also enhances security to prevent secrets from leaking into a container by accident.
|
||||
- Don't install unneccesary packages. In lieu of multi-stage builds, build caches and build dependencies are removed before finalizing the container. Only packages that are necessary for the execution of the application are installed. This is why `git` is not present.
|
||||
- Don't install unnecessary packages. In lieu of multi-stage builds, build caches and build dependencies are removed before finalizing the container. Only packages that are necessary for the execution of the application are installed. This is why `git` is not present.
|
||||
- Minimize the number of layers. Many `RUN` commands are combined into one using `&&` in order to reduce the number of layers.
|
||||
- Sort multiline arguments. This mostly enhances readability and maintainability.
|
||||
- Leverage build cache. When testing locally, several of the tips above help levarage the build cache and speed up build times.
|
||||
- Leverage build cache. When testing locally, several of the tips above help leverage the build cache and speed up build times.
|
||||
|
||||
### Twelve Factor App
|
||||
|
||||
|
||||
+7
-3
@@ -12,11 +12,11 @@ exports.newEnvironment = function () {
|
||||
BASE_PATH: basePath,
|
||||
WEB_SERVER_URL: 'localhost',
|
||||
PLATFORM_WEB_SOCKETS_INTERFACE_PORT: 18041,
|
||||
NETWORK_WEB_SOCKETS_INTERFACE_PORT: 18042,
|
||||
DESKTOP_WEB_SOCKETS_INTERFACE_PORT: 18043,
|
||||
NETWORK_WEB_SOCKETS_INTERFACE_PORT: 17041,
|
||||
DESKTOP_WEB_SOCKETS_INTERFACE_PORT: 16041,
|
||||
DESKTOP_WEB_SOCKETS_INTERFACE_HOST: 'localhost',
|
||||
PLATFORM_HTTP_INTERFACE_PORT: 34248,
|
||||
DESKTOP_HTTP_INTERFACE_PORT: 34249,
|
||||
DESKTOP_HTTP_INTERFACE_PORT: 33248,
|
||||
PATH_TO_DATA_STORAGE: path.join(basePath, './Platform/My-Data-Storage'),
|
||||
PATH_TO_PROJECTS: path.join(basePath, './Projects'),
|
||||
PATH_TO_LOG_FILES: path.join(basePath, './Platform/My-Log-Files'),
|
||||
@@ -28,10 +28,14 @@ exports.newEnvironment = function () {
|
||||
PATH_TO_MY_WORKSPACES: path.join(basePath, './Platform/My-Workspaces'),
|
||||
PATH_TO_FONTS: path.join(basePath, './Platform/WebServer/Fonts'),
|
||||
DESKTOP_APP_SIGNING_ACCOUNT: 'Social-Trading-Desktop-App-1',
|
||||
DESKTOP_APP_MAX_OUTGOING_PEERS: 2,
|
||||
MOBILE_APP_SIGNING_ACCOUNT: 'Social-Trading-Mobile-App-1',
|
||||
SERVER_APP_SIGNING_ACCOUNT: 'Social-Trading-Server-App-1',
|
||||
PLATFORM_APP_SIGNING_ACCOUNT: 'Algo-Traders-Platform-1',
|
||||
P2P_NETWORK_NODE_SIGNING_ACCOUNT: 'P2P-Network-Node-1',
|
||||
P2P_NETWORK_NODE_MAX_INCOMING_CLIENTS: 20,
|
||||
P2P_NETWORK_NODE_MAX_INCOMING_PEERS: 2,
|
||||
P2P_NETWORK_NODE_MAX_OUTGOING_PEERS: 2
|
||||
}
|
||||
|
||||
if (process.env.DATA_PATH) {
|
||||
|
||||
+57
-15
@@ -1,28 +1,70 @@
|
||||
exports.newNetworkNode = function newNetworkNode() {
|
||||
|
||||
let thisObject = {
|
||||
userProfiles: undefined,
|
||||
p2pNetwork: undefined,
|
||||
p2pNetworkPeers: undefined,
|
||||
p2pNetworkNode: undefined,
|
||||
webSocketsInterface: undefined,
|
||||
socialGraphService: undefined,
|
||||
storage: undefined,
|
||||
run: run
|
||||
}
|
||||
|
||||
NT.networkNode = thisObject
|
||||
|
||||
return thisObject
|
||||
|
||||
async function run() {
|
||||
/*
|
||||
Other Network Nodes and Client Apps will communicate with this Network Node via it's Websocket Interface.
|
||||
*/
|
||||
NT.webSocketsInterface = NT.projects.network.modules.webSocketsInterface.newNetworkModulesWebSocketsInterface()
|
||||
NT.webSocketsInterface.initialize()
|
||||
/*
|
||||
The Social Graph Service is the first and for now, the only service this Network Node provides.
|
||||
*/
|
||||
thisObject.socialGraphService = NT.projects.socialTrading.modules.socialGraph.newNetworkModulesSocialGraph()
|
||||
await thisObject.socialGraphService.initialize()
|
||||
/*
|
||||
The Sotrage deals with persisting the Social Graph.
|
||||
*/
|
||||
thisObject.storage = NT.projects.socialTrading.modules.storage.newSocialTradingModulesStorage()
|
||||
thisObject.storage.initialize()
|
||||
|
||||
await setupNetwork()
|
||||
await setupServices()
|
||||
|
||||
async function setupNetwork() {
|
||||
/*
|
||||
We set up ourselves as a Network Node.
|
||||
*/
|
||||
thisObject.p2pNetworkNode = SA.projects.network.modules.p2pNetworkNode.newNetworkModulesP2PNetworkNode()
|
||||
await thisObject.p2pNetworkNode.initialize()
|
||||
/*
|
||||
We will read all user profiles plugins and get from there our network identity.
|
||||
*/
|
||||
thisObject.userProfiles = SA.projects.network.modules.userProfiles.newNetworkModulesUserProfiles()
|
||||
await thisObject.userProfiles.initialize(global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT, thisObject.p2pNetworkNode)
|
||||
/*
|
||||
Let's discover who is at the p2p network.
|
||||
*/
|
||||
thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork()
|
||||
await thisObject.p2pNetwork.initialize('Network Peer')
|
||||
/*
|
||||
Set up the connections to network nodes.
|
||||
*/
|
||||
thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers()
|
||||
await thisObject.p2pNetworkPeers.initialize(
|
||||
'Network Peer',
|
||||
thisObject.p2pNetworkNode,
|
||||
thisObject.p2pNetwork,
|
||||
global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS
|
||||
)
|
||||
}
|
||||
|
||||
async function setupServices() {
|
||||
/*
|
||||
The Social Graph Service is the first and for now, the only service this Network Node provides.
|
||||
*/
|
||||
thisObject.socialGraphService = NT.projects.socialTrading.modules.socialGraph.newNetworkModulesSocialGraph()
|
||||
await thisObject.socialGraphService.initialize()
|
||||
/*
|
||||
The Sotrage deals with persisting the Social Graph.
|
||||
*/
|
||||
thisObject.storage = NT.projects.socialTrading.modules.storage.newSocialTradingModulesStorage()
|
||||
thisObject.storage.initialize()
|
||||
/*
|
||||
Other Network Nodes and Client Apps will communicate with this Network Node via it's Websocket Interface.
|
||||
*/
|
||||
thisObject.webSocketsInterface = NT.projects.network.modules.webSocketsInterface.newNetworkModulesWebSocketsInterface()
|
||||
thisObject.webSocketsInterface.initialize()
|
||||
console.log('Network Node Web Sockets Interface ........................................... Listening at port ' + JSON.parse(NT.networkNode.p2pNetworkNode.node.config).webSocketsPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -10,7 +10,7 @@ exports.newNetworkRoot = function newNetworkRoot() {
|
||||
|
||||
return thisObject
|
||||
|
||||
async function run() {
|
||||
async function run(debugSettings) {
|
||||
/*
|
||||
The NT object is accessible everywhere at the Superalgos Network.
|
||||
It provides access to all modules built for this Network.
|
||||
@@ -25,6 +25,10 @@ exports.newNetworkRoot = function newNetworkRoot() {
|
||||
let ENVIRONMENT = require('./Environment.js');
|
||||
let ENVIRONMENT_MODULE = ENVIRONMENT.newEnvironment()
|
||||
global.env = ENVIRONMENT_MODULE
|
||||
|
||||
if (debugSettings !== undefined && debugSettings.P2P_NETWORK_NODE_SIGNING_ACCOUNT !== undefined) {
|
||||
global.env.P2P_NETWORK_NODE_SIGNING_ACCOUNT = debugSettings.P2P_NETWORK_NODE_SIGNING_ACCOUNT
|
||||
}
|
||||
/*
|
||||
First thing is to load the project schema file.
|
||||
*/
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
let path = global.env.BASE_PATH + '/TaskServerRoot.js'
|
||||
|
||||
/* Workarround to avoid having the same debug port at the forked process which makes it crash. */
|
||||
/* Workaround to avoid having the same debug port at the forked process which makes it crash. */
|
||||
for (let i = 0; i < process.execArgv.length; i++) {
|
||||
let argument = process.execArgv[i]
|
||||
if (argument.indexOf('--inspect') > -1) {
|
||||
@@ -94,7 +94,7 @@
|
||||
console.log(`[ERROR] Client -> Task Manager Server -> runTask -> Task Server exited with error ${err}`)
|
||||
tasksMap.delete(task.id)
|
||||
})
|
||||
/* If the Tast Server stops, we remove it from our task map */
|
||||
/* If the Task Server stops, we remove it from our task map */
|
||||
task.childProcess.on('close', (code, signal) => {
|
||||
//console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Terminated. -> Task Name = ' + task.name)
|
||||
//console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Terminated. -> Task Id = ' + task.id)
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
|
||||
function finalize() {
|
||||
/* Before disconnecting we will forze all eventListeners to stop listening. */
|
||||
/* Before disconnecting we will force all eventListeners to stop listening. */
|
||||
const eventListenersArray = [...eventListeners.values()]
|
||||
for (let i = 0; i < eventListenersArray.length; i++) {
|
||||
let handler = eventListenersArray[i]
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
try {
|
||||
if (global.env.DEMO_MODE === true) {
|
||||
/*
|
||||
In DEMO MODE we will accept Task / Sessioins Running or Stopping if you are requesting this from localhost only.
|
||||
In DEMO MODE we will accept Task / Sessions Running or Stopping if you are requesting this from localhost only.
|
||||
*/
|
||||
if (socket._socket.remoteAddress !== "::1") {
|
||||
if (
|
||||
|
||||
@@ -20,7 +20,7 @@ exports.newPlatformApp = function newPlatformApp() {
|
||||
})
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
// Signal user that a necissary node module is missing
|
||||
// Signal user that a necessary node module is missing
|
||||
if (reason.code == 'MODULE_NOT_FOUND') {
|
||||
console.log("[ERROR] Dependency library not found. Please try running the 'node setup' command and then restart the Superalgos Platform Client.")
|
||||
console.log('[ERROR] Platform App -> reason = ' + JSON.stringify(reason))
|
||||
|
||||
@@ -515,6 +515,11 @@ function newCanvas() {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (nodeOnFocus.payload.uiObject.listSelector !== undefined) {
|
||||
if (nodeOnFocus.payload.uiObject.listSelector.visible === true) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (nodeOnFocus.payload.uiObject.conditionEditor !== undefined) {
|
||||
if (nodeOnFocus.payload.uiObject.conditionEditor.visible === true) {
|
||||
return
|
||||
|
||||
@@ -8,7 +8,7 @@ function newProductStorage(name) {
|
||||
/*
|
||||
|
||||
This object will initialize children objects that will end up loading the data of each set defined at each product of the bot received at initialization.
|
||||
Once all the underlaying objects are fully initialized it will callback.
|
||||
Once all the underlying objects are fully initialized it will callback.
|
||||
|
||||
At the same time it will raise an event for each underlaying file being loaded, so that the UI can reflect the progress to the end user.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ function getSchemaDocument(node, project) {
|
||||
even those can fail. For that reason, we will temporally see if we can find the schema document at any of the
|
||||
available projects.
|
||||
|
||||
TODO: We need to explictly declare the project of a relatedUIObject in order to avoid potential name collision
|
||||
TODO: We need to explicitly declare the project of a relatedUIObject in order to avoid potential name collision
|
||||
between nodes belonging to more than one project.
|
||||
*/
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
File renamed without changes.
@@ -0,0 +1,33 @@
|
||||
/**!
|
||||
* FlexSearch.js v0.7.2 (Bundle)
|
||||
* Copyright 2018-2021 Nextapps GmbH
|
||||
* Author: Thomas Wilkerling
|
||||
* Licence: Apache-2.0
|
||||
* https://github.com/nextapps-de/flexsearch
|
||||
*/
|
||||
(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var t;function u(a){return"undefined"!==typeof a?a:!0}function aa(a){const b=Array(a);for(let c=0;c<a;c++)b[c]=v();return b}function v(){return Object.create(null)}function ba(a,b){return b.length-a.length}function x(a){return"string"===typeof a}function C(a){return"object"===typeof a}function D(a){return"function"===typeof a};function ca(a,b){var c=da;if(a&&(b&&(a=E(a,b)),this.H&&(a=E(a,this.H)),this.J&&1<a.length&&(a=E(a,this.J)),c||""===c)){a=a.split(c);if(this.filter){b=this.filter;c=a.length;const d=[];for(let e=0,f=0;e<c;e++){const g=a[e];g&&!b[g]&&(d[f++]=g)}a=d}return a}return a}const da=/[\p{Z}\p{S}\p{P}\p{C}]+/u,ea=/[\u0300-\u036f]/g;
|
||||
function fa(a,b){const c=Object.keys(a),d=c.length,e=[];let f="",g=0;for(let h=0,k,m;h<d;h++)k=c[h],(m=a[k])?(e[g++]=F(b?"(?!\\b)"+k+"(\\b|_)":k),e[g++]=m):f+=(f?"|":"")+k;f&&(e[g++]=F(b?"(?!\\b)("+f+")(\\b|_)":"("+f+")"),e[g]="");return e}function E(a,b){for(let c=0,d=b.length;c<d&&(a=a.replace(b[c],b[c+1]),a);c+=2);return a}function F(a){return new RegExp(a,"g")}function ha(a){let b="",c="";for(let d=0,e=a.length,f;d<e;d++)(f=a[d])!==c&&(b+=c=f);return b};var ja={encode:ia,F:!1,G:""};function ia(a){return ca.call(this,a.toLowerCase(),!1)};const ka={},G={};function la(a){I(a,"add");I(a,"append");I(a,"search");I(a,"update");I(a,"remove")}function I(a,b){a[b+"Async"]=function(){const c=this,d=arguments;var e=d[d.length-1];let f;D(e)&&(f=e,delete d[d.length-1]);e=new Promise(function(g){setTimeout(function(){c.async=!0;const h=c[b].apply(c,d);c.async=!1;g(h)})});return f?(e.then(f),this):e}};function ma(a,b,c,d){const e=a.length;let f=[],g,h,k=0;d&&(d=[]);for(let m=e-1;0<=m;m--){const n=a[m],w=n.length,q=v();let r=!g;for(let l=0;l<w;l++){const p=n[l],z=p.length;if(z)for(let B=0,A,y;B<z;B++)if(y=p[B],g){if(g[y]){if(!m)if(c)c--;else if(f[k++]=y,k===b)return f;if(m||d)q[y]=1;r=!0}if(d&&(h[y]=(A=h[y])?++A:A=1,A<e)){const H=d[A-2]||(d[A-2]=[]);H[H.length]=y}}else q[y]=1}if(d)g||(h=q);else if(!r)return[];g=q}if(d)for(let m=d.length-1,n,w;0<=m;m--){n=d[m];w=n.length;for(let q=0,r;q<w;q++)if(r=
|
||||
n[q],!g[r]){if(c)c--;else if(f[k++]=r,k===b)return f;g[r]=1}}return f}function na(a,b){const c=v(),d=v(),e=[];for(let f=0;f<a.length;f++)c[a[f]]=1;for(let f=0,g;f<b.length;f++){g=b[f];for(let h=0,k;h<g.length;h++)k=g[h],c[k]&&!d[k]&&(d[k]=1,e[e.length]=k)}return e};function J(a){this.l=!0!==a&&a;this.cache=v();this.h=[]}function oa(a,b,c){C(a)&&(a=a.query);let d=this.cache.get(a);d||(d=this.search(a,b,c),this.cache.set(a,d));return d}J.prototype.set=function(a,b){if(!this.cache[a]){var c=this.h.length;c===this.l?delete this.cache[this.h[c-1]]:c++;for(--c;0<c;c--)this.h[c]=this.h[c-1];this.h[0]=a}this.cache[a]=b};J.prototype.get=function(a){const b=this.cache[a];if(this.l&&b&&(a=this.h.indexOf(a))){const c=this.h[a-1];this.h[a-1]=this.h[a];this.h[a]=c}return b};const qa={memory:{charset:"latin:extra",D:3,B:4,m:!1},performance:{D:3,B:3,s:!1,context:{depth:2,D:1}},match:{charset:"latin:extra",G:"reverse"},score:{charset:"latin:advanced",D:20,B:3,context:{depth:3,D:9}},"default":{}};function ra(a,b,c,d,e,f){setTimeout(function(){const g=a(c,JSON.stringify(f));g&&g.then?g.then(function(){b.export(a,b,c,d,e+1)}):b.export(a,b,c,d,e+1)})};function K(a,b){if(!(this instanceof K))return new K(a);var c;if(a){x(a)?a=qa[a]:(c=a.preset)&&(a=Object.assign({},c[c],a));c=a.charset;var d=a.lang;x(c)&&(-1===c.indexOf(":")&&(c+=":default"),c=G[c]);x(d)&&(d=ka[d])}else a={};let e,f,g=a.context||{};this.encode=a.encode||c&&c.encode||ia;this.register=b||v();this.D=e=a.resolution||9;this.G=b=c&&c.G||a.tokenize||"strict";this.depth="strict"===b&&g.depth;this.l=u(g.bidirectional);this.s=f=u(a.optimize);this.m=u(a.fastupdate);this.B=a.minlength||1;this.C=
|
||||
a.boost;this.map=f?aa(e):v();this.A=e=g.resolution||1;this.h=f?aa(e):v();this.F=c&&c.F||a.rtl;this.H=(b=a.matcher||d&&d.H)&&fa(b,!1);this.J=(b=a.stemmer||d&&d.J)&&fa(b,!0);if(c=b=a.filter||d&&d.filter){c=b;d=v();for(let h=0,k=c.length;h<k;h++)d[c[h]]=1;c=d}this.filter=c;this.cache=(b=a.cache)&&new J(b)}t=K.prototype;t.append=function(a,b){return this.add(a,b,!0)};
|
||||
t.add=function(a,b,c,d){if(b&&(a||0===a)){if(!d&&!c&&this.register[a])return this.update(a,b);b=this.encode(b);if(d=b.length){const m=v(),n=v(),w=this.depth,q=this.D;for(let r=0;r<d;r++){let l=b[this.F?d-1-r:r];var e=l.length;if(l&&e>=this.B&&(w||!n[l])){var f=L(q,d,r),g="";switch(this.G){case "full":if(3<e){for(f=0;f<e;f++)for(var h=e;h>f;h--)if(h-f>=this.B){var k=L(q,d,r,e,f);g=l.substring(f,h);M(this,n,g,k,a,c)}break}case "reverse":if(2<e){for(h=e-1;0<h;h--)g=l[h]+g,g.length>=this.B&&M(this,n,
|
||||
g,L(q,d,r,e,h),a,c);g=""}case "forward":if(1<e){for(h=0;h<e;h++)g+=l[h],g.length>=this.B&&M(this,n,g,f,a,c);break}default:if(this.C&&(f=Math.min(f/this.C(b,l,r)|0,q-1)),M(this,n,l,f,a,c),w&&1<d&&r<d-1)for(e=v(),g=this.A,f=l,h=Math.min(w+1,d-r),e[f]=1,k=1;k<h;k++)if((l=b[this.F?d-1-r-k:r+k])&&l.length>=this.B&&!e[l]){e[l]=1;const p=this.l&&l>f;M(this,m,p?f:l,L(g+(d/2>g?0:1),d,r,h-1,k-1),a,c,p?l:f)}}}}this.m||(this.register[a]=1)}}return this};
|
||||
function L(a,b,c,d,e){return c&&1<a?b+(d||0)<=a?c+(e||0):(a-1)/(b+(d||0))*(c+(e||0))+1|0:0}function M(a,b,c,d,e,f,g){let h=g?a.h:a.map;if(!b[c]||g&&!b[c][g])a.s&&(h=h[d]),g?(b=b[c]||(b[c]=v()),b[g]=1,h=h[g]||(h[g]=v())):b[c]=1,h=h[c]||(h[c]=[]),a.s||(h=h[d]||(h[d]=[])),f&&-1!==h.indexOf(e)||(h[h.length]=e,a.m&&(a=a.register[e]||(a.register[e]=[]),a[a.length]=h))}
|
||||
t.search=function(a,b,c){c||(!b&&C(a)?(c=a,a=c.query):C(b)&&(c=b));let d=[],e;let f,g=0;if(c){b=c.limit;g=c.offset||0;var h=c.context;f=c.suggest}if(a&&(a=this.encode(a),e=a.length,1<e)){c=v();var k=[];for(let n=0,w=0,q;n<e;n++)if((q=a[n])&&q.length>=this.B&&!c[q])if(this.s||f||this.map[q])k[w++]=q,c[q]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1<e&&!1!==h;c=0;let m;h?(m=a[0],c=1):1<e&&a.sort(ba);for(let n,w;c<e;c++){w=a[c];h?(n=sa(this,d,f,b,g,2===e,w,m),f&&!1===n&&d.length||
|
||||
(m=w)):n=sa(this,d,f,b,g,1===e,w);if(n)return n;if(f&&c===e-1){k=d.length;if(!k){if(h){h=0;c=-1;continue}return d}if(1===k)return ta(d[0],b,g)}}return ma(d,b,g,f)};
|
||||
function sa(a,b,c,d,e,f,g,h){let k=[],m=h?a.h:a.map;a.s||(m=ua(m,g,h,a.l));if(m){let n=0;const w=Math.min(m.length,h?a.A:a.D);for(let q=0,r=0,l,p;q<w;q++)if(l=m[q])if(a.s&&(l=ua(l,g,h,a.l)),e&&l&&f&&(p=l.length,p<=e?(e-=p,l=null):(l=l.slice(e),e=0)),l&&(k[n++]=l,f&&(r+=l.length,r>=d)))break;if(n){if(f)return ta(k,d,0);b[b.length]=k;return}}return!c&&k}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a}
|
||||
function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)};
|
||||
t.remove=function(a,b){const c=this.register[a];if(c){if(this.m)for(let d=0,e;d<c.length;d++)e=c[d],e.splice(e.indexOf(a),1);else N(this.map,a,this.D,this.s),this.depth&&N(this.h,a,this.A,this.s);b||delete this.register[a];if(this.cache){b=this.cache;for(let d=0,e,f;d<b.h.length;d++)f=b.h[d],e=b.cache[f],-1!==e.indexOf(a)&&(b.h.splice(d--,1),delete b.cache[f])}}return this};
|
||||
function N(a,b,c,d,e){let f=0;if(a.constructor===Array)if(e)b=a.indexOf(b),-1!==b?1<a.length&&(a.splice(b,1),f++):f++;else{e=Math.min(a.length,c);for(let g=0,h;g<e;g++)if(h=a[g])f=N(h,b,c,d,e),d||f||delete a[g]}else for(let g in a)(f=N(a[g],b,c,d,e))||delete a[g];return f}t.searchCache=oa;
|
||||
t.export=function(a,b,c,d,e){let f,g;switch(e||(e=0)){case 0:f="reg";if(this.m){g=v();for(let h in this.register)g[h]=1}else g=this.register;break;case 1:f="cfg";g={doc:0,opt:this.s?1:0};break;case 2:f="map";g=this.map;break;case 3:f="ctx";g=this.h;break;default:return}ra(a,b||this,c?c+"."+f:f,d,e,g);return!0};t.import=function(a,b){if(b)switch(x(b)&&(b=JSON.parse(b)),a){case "cfg":this.s=!!b.opt;break;case "reg":this.m=!1;this.register=b;break;case "map":this.map=b;break;case "ctx":this.h=b}};la(K.prototype);function va(a){a=a.data;var b=self._index;const c=a.args;var d=a.task;switch(d){case "init":d=a.options||{};a=a.factory;b=d.encode;d.cache=!1;b&&0===b.indexOf("function")&&(d.encode=Function("return "+b)());a?(Function("return "+a)()(self),self._index=new self.FlexSearch.Index(d),delete self.FlexSearch):self._index=new K(d);break;default:a=a.id,b=b[d].apply(b,c),postMessage("search"===d?{id:a,msg:b}:{id:a})}};let wa=0;function O(a){if(!(this instanceof O))return new O(a);var b;a?D(b=a.encode)&&(a.encode=b.toString()):a={};(b=(self||window)._factory)&&(b=b.toString());const c=self.exports,d=this;this.o=xa(b,c,a.worker);this.h=v();if(this.o){if(c)this.o.on("message",function(e){d.h[e.id](e.msg);delete d.h[e.id]});else this.o.onmessage=function(e){e=e.data;d.h[e.id](e.msg);delete d.h[e.id]};this.o.postMessage({task:"init",factory:b,options:a})}}P("add");P("append");P("search");P("update");P("remove");
|
||||
function P(a){O.prototype[a]=O.prototype[a+"Async"]=function(){const b=this,c=[].slice.call(arguments);var d=c[c.length-1];let e;D(d)&&(e=d,c.splice(c.length-1,1));d=new Promise(function(f){setTimeout(function(){b.h[++wa]=f;b.o.postMessage({task:a,id:wa,args:c})})});return e?(d.then(e),this):d}}
|
||||
function xa(a,b,c){let d;try{d=b?eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")'):a?new Worker(URL.createObjectURL(new Blob(["onmessage="+va.toString()],{type:"text/javascript"}))):new Worker(x(c)?c:"worker/worker.js",{type:"module"})}catch(e){}return d};function Q(a){if(!(this instanceof Q))return new Q(a);var b=a.document||a.doc||a,c;this.K=[];this.h=[];this.A=[];this.register=v();this.key=(c=b.key||b.id)&&S(c,this.A)||"id";this.m=u(a.fastupdate);this.C=(c=b.store)&&!0!==c&&[];this.store=c&&v();this.I=(c=b.tag)&&S(c,this.A);this.l=c&&v();this.cache=(c=a.cache)&&new J(c);a.cache=!1;this.o=a.worker;this.async=!1;c=v();let d=b.index||b.field||b;x(d)&&(d=[d]);for(let e=0,f,g;e<d.length;e++)f=d[e],x(f)||(g=f,f=f.field),g=C(g)?Object.assign({},a,g):a,
|
||||
this.o&&(c[f]=new O(g),c[f].o||(this.o=!1)),this.o||(c[f]=new K(g,this.register)),this.K[e]=S(f,this.A),this.h[e]=f;if(this.C)for(a=b.store,x(a)&&(a=[a]),b=0;b<a.length;b++)this.C[b]=S(a[b],this.A);this.index=c}function S(a,b){const c=a.split(":");let d=0;for(let e=0;e<c.length;e++)a=c[e],0<=a.indexOf("[]")&&(a=a.substring(0,a.length-2))&&(b[d]=!0),a&&(c[d++]=a);d<c.length&&(c.length=d);return 1<d?c:c[0]}function T(a,b){if(x(b))a=a[b];else for(let c=0;a&&c<b.length;c++)a=a[b[c]];return a}
|
||||
function U(a,b,c,d,e){a=a[e];if(d===c.length-1)b[e]=a;else if(a)if(a.constructor===Array)for(b=b[e]=Array(a.length),e=0;e<a.length;e++)U(a,b,c,d,e);else b=b[e]||(b[e]=v()),e=c[++d],U(a,b,c,d,e)}function V(a,b,c,d,e,f,g,h){if(a=a[g])if(d===b.length-1){if(a.constructor===Array){if(c[d]){for(b=0;b<a.length;b++)e.add(f,a[b],!0,!0);return}a=a.join(" ")}e.add(f,a,h,!0)}else if(a.constructor===Array)for(g=0;g<a.length;g++)V(a,b,c,d,e,f,g,h);else g=b[++d],V(a,b,c,d,e,f,g,h)}t=Q.prototype;
|
||||
t.add=function(a,b,c){C(a)&&(b=a,a=T(b,this.key));if(b&&(a||0===a)){if(!c&&this.register[a])return this.update(a,b);for(let d=0,e,f;d<this.h.length;d++)f=this.h[d],e=this.K[d],x(e)&&(e=[e]),V(b,e,this.A,0,this.index[f],a,e[0],c);if(this.I){let d=T(b,this.I),e=v();x(d)&&(d=[d]);for(let f=0,g,h;f<d.length;f++)if(g=d[f],!e[g]&&(e[g]=1,h=this.l[g]||(this.l[g]=[]),!c||-1===h.indexOf(a)))if(h[h.length]=a,this.m){const k=this.register[a]||(this.register[a]=[]);k[k.length]=h}}if(this.store&&(!c||!this.store[a])){let d;
|
||||
if(this.C){d=v();for(let e=0,f;e<this.C.length;e++)f=this.C[e],x(f)?d[f]=b[f]:U(b,d,f,0,f[0])}this.store[a]=d||b}}return this};t.append=function(a,b){return this.add(a,b,!0)};t.update=function(a,b){return this.remove(a).add(a,b)};
|
||||
t.remove=function(a){C(a)&&(a=T(a,this.key));if(this.register[a]){for(var b=0;b<this.h.length&&(this.index[this.h[b]].remove(a,!this.o),!this.m);b++);if(this.I&&!this.m)for(let c in this.l){b=this.l[c];const d=b.indexOf(a);-1!==d&&(1<b.length?b.splice(d,1):delete this.l[c])}this.store&&delete this.store[a];delete this.register[a]}return this};
|
||||
t.search=function(a,b,c,d){c||(!b&&C(a)?(c=a,a=c.query):C(b)&&(c=b,b=0));let e=[],f=[],g,h,k,m,n,w,q=0;if(c)if(c.constructor===Array)k=c,c=null;else{k=(g=c.pluck)||c.index||c.field;m=c.tag;h=this.store&&c.enrich;n="and"===c.bool;b=c.limit||100;w=c.offset||0;if(m&&(x(m)&&(m=[m]),!a)){for(let l=0,p;l<m.length;l++)if(p=ya.call(this,m[l],b,w,h))e[e.length]=p,q++;return q?e:[]}x(k)&&(k=[k])}k||(k=this.h);n=n&&(1<k.length||m&&1<m.length);const r=!d&&(this.o||this.async)&&[];for(let l=0,p,z,B;l<k.length;l++){let A;
|
||||
z=k[l];x(z)||(A=z,z=z.field);if(r)r[l]=this.index[z].searchAsync(a,b,A||c);else{d?p=d[l]:p=this.index[z].search(a,b,A||c);B=p&&p.length;if(m&&B){const y=[];let H=0;n&&(y[0]=[p]);for(let X=0,pa,R;X<m.length;X++)if(pa=m[X],B=(R=this.l[pa])&&R.length)H++,y[y.length]=n?[R]:R;H&&(p=n?ma(y,b||100,w||0):na(p,y),B=p.length)}if(B)f[q]=z,e[q++]=p;else if(n)return[]}}if(r){const l=this;return new Promise(function(p){Promise.all(r).then(function(z){p(l.search(a,b,c,z))})})}if(!q)return[];if(g&&(!h||!this.store))return e[0];
|
||||
for(let l=0,p;l<f.length;l++){p=e[l];p.length&&h&&(p=za.call(this,p));if(g)return p;e[l]={field:f[l],result:p}}return e};function ya(a,b,c,d){let e=this.l[a],f=e&&e.length-c;if(f&&0<f){if(f>b||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c<a.length;c++)d=a[c],b[c]={id:d,doc:this.store[d]};return b}t.contain=function(a){return!!this.register[a]};t.get=function(a){return this.store[a]};t.set=function(a,b){this.store[a]=b;return this};
|
||||
t.searchCache=oa;t.export=function(a,b,c,d,e){e||(e=0);d||(d=0);if(d<this.h.length){const f=this.h[d],g=this.index[f];b=this;setTimeout(function(){g.export(a,b,e?f.replace(":","-"):"",d,e++)||(d++,e=1,b.export(a,b,f,d,e))})}else{let f;switch(e){case 1:c="tag";f=this.l;break;case 2:c="store";f=this.store;break;default:return}ra(a,this,c,d,e,f)}};
|
||||
t.import=function(a,b){if(b)switch(x(b)&&(b=JSON.parse(b)),a){case "tag":this.l=b;break;case "reg":this.m=!1;this.register=b;for(let d=0,e;d<this.h.length;d++)e=this.index[this.h[d]],e.register=b,e.m=!1;break;case "store":this.store=b;break;default:a=a.split(".");const c=a[0];a=a[1];c&&a&&this.index[c].import(a,b)}};la(Q.prototype);var Ba={encode:Aa,F:!1,G:""};const Ca=[F("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"),"a",F("[\u00e8\u00e9\u00ea\u00eb]"),"e",F("[\u00ec\u00ed\u00ee\u00ef]"),"i",F("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"),"o",F("[\u00f9\u00fa\u00fb\u00fc\u0171]"),"u",F("[\u00fd\u0177\u00ff]"),"y",F("\u00f1"),"n",F("[\u00e7c]"),"k",F("\u00df"),"s",F(" & ")," and "];function Aa(a){var b=a;b.normalize&&(b=b.normalize("NFD").replace(ea,""));return ca.call(this,b.toLowerCase(),!a.normalize&&Ca)};var Ea={encode:Da,F:!1,G:"strict"};const Fa=/[^a-z0-9]+/,Ga={b:"p",v:"f",w:"f",z:"s",x:"s","\u00df":"s",d:"t",n:"m",c:"k",g:"k",j:"k",q:"k",i:"e",y:"e",u:"o"};function Da(a){a=Aa.call(this,a).join(" ");const b=[];if(a){const c=a.split(Fa),d=c.length;for(let e=0,f,g=0;e<d;e++)if((a=c[e])&&(!this.filter||!this.filter[a])){f=a[0];let h=Ga[f]||f,k=h;for(let m=1;m<a.length;m++){f=a[m];const n=Ga[f]||f;n&&n!==k&&(h+=n,k=n)}b[g++]=h}}return b};var Ia={encode:Ha,F:!1,G:""};const Ja=[F("ae"),"a",F("oe"),"o",F("sh"),"s",F("th"),"t",F("ph"),"f",F("pf"),"f",F("(?![aeo])h(?![aeo])"),"",F("(?!^[aeo])h(?!^[aeo])"),""];function Ha(a,b){a&&(a=Da.call(this,a).join(" "),2<a.length&&(a=E(a,Ja)),b||(1<a.length&&(a=ha(a)),a&&(a=a.split(" "))));return a};var La={encode:Ka,F:!1,G:""};const Ma=F("(?!\\b)[aeo]");function Ka(a){a&&(a=Ha.call(this,a,!0),1<a.length&&(a=a.replace(Ma,"")),1<a.length&&(a=ha(a)),a&&(a=a.split(" ")));return a};G["latin:default"]=ja;G["latin:simple"]=Ba;G["latin:balance"]=Ea;G["latin:advanced"]=Ia;G["latin:extra"]=La;const W=self;let Y;const Z={Index:K,Document:Q,Worker:O,registerCharset:function(a,b){G[a]=b},registerLanguage:function(a,b){ka[a]=b}};(Y=W.define)&&Y.amd?Y([],function(){return Z}):W.exports?W.exports=Z:W.FlexSearch=Z;}(this));
|
||||
@@ -17,6 +17,7 @@
|
||||
<script type="text/javascript" src="AppPreLoader.js"></script>
|
||||
<script src="externalScripts/CCapture.all.min.js"></script>
|
||||
<script src="externalScripts/prism.js"></script>
|
||||
<script src="externalScripts/flexsearch.bundle.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function loadApp() {
|
||||
|
||||
+3
-2
@@ -6,12 +6,12 @@ load all node dependencies and get them ready to the actual App.
|
||||
*/
|
||||
|
||||
/*
|
||||
The PL object is accesible everywhere at the Superalgos Platform Client.
|
||||
The PL object is accessible everywhere at the Superalgos Platform Client.
|
||||
It provides access to all modules built for this Client.
|
||||
*/
|
||||
global.PL = {}
|
||||
/*
|
||||
The SA object is accesible everywhere at the Superalgos Desktop App.
|
||||
The SA object is accessible everywhere at the Superalgos Desktop App.
|
||||
It provides access to all modules built for Superalgos in general.
|
||||
*/
|
||||
global.SA = {}
|
||||
@@ -53,6 +53,7 @@ SA.nodeModules = {
|
||||
lookpath: require('lookpath'),
|
||||
process: require('process'),
|
||||
childProcess: require('child_process')
|
||||
|
||||
}
|
||||
/*
|
||||
Check if we are starting from a particular workspace.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -8,6 +8,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un Trading Bot es un programa informático que, basado en conjuntos de datos expuestos como productos por otros bots (sensores de conteo, indicadores e incluso otros trading bots ), aplica la lógica trading definida en un Trading System para, por un lado, generar una simulación de trading completa (generando conjuntos de datos que incluyen operaciones, la acción de estrategias, validación de condiciones, etc.) y, por otro lado, gestiona la ejecución de órdenes en una sesión ya sea en vivo o no.",
|
||||
"updated": 1624375084844
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Торговый бот — это компьютерная программа, которая на основе наборов данных, представленных в качестве продуктов другими ботами (датчики подсчета, индикаторы и даже другие торговые боты), применяет торговую логику, определенную в торговой системе, с одной стороны, для создания полной торговой симуляции (вывод наборов данных, которые включают сделки, действие стратегий, проверку условий и т. д.), а с другой стороны, управляет исполнением ордеров во время форвардного тестирования или реальной торговой сессии.",
|
||||
"updated": 1636194335057
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+5
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un trading system es un marco que maneja la lógica de bajo nivel que sirve para estructurar los procesos y métodos utilizados para implementar y desplegar estrategias de trading.",
|
||||
"updated": 1624375355452
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Торговая система - это структура, управляющая логикой низкого уровня, которая служит для структурирования процессов и методов, используемых для реализации и развертывания торговых стратегий.",
|
||||
"updated": 1636194401995
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processIndex) {
|
||||
/*
|
||||
When we are live trading, we need to syncronize with the exchange.
|
||||
When we are live trading, we need to synchronize with the exchange.
|
||||
*/
|
||||
|
||||
let thisObject = {
|
||||
@@ -48,7 +48,7 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
|
||||
If it happens that the size accepted (Actual Size) is different than the
|
||||
size requested (Size), we need to make several adjustments so that the
|
||||
accounting syncronizes with reality.
|
||||
accounting synchronizes with reality.
|
||||
*/
|
||||
|
||||
/* This calculation needs to happen only once, the first time the order is checked. */
|
||||
@@ -65,8 +65,8 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
function recalculateActualSize() {
|
||||
/*
|
||||
We will recalculate the Quoted Asset Actual Size. This will also give to it an initial value.
|
||||
In the next formula, we are unsing the rate of the order because we dont know yet the Actual Rate.
|
||||
This rate might be replaced afteerwards for the Actual Rate when this is calculated again once
|
||||
In the next formula, we are using the rate of the order because we dont know yet the Actual Rate.
|
||||
This rate might be replaced afterwards for the Actual Rate when this is calculated again once
|
||||
the Actual Rate is known.
|
||||
*/
|
||||
tradingEngineOrder.orderQuotedAsset.actualSize.value = tradingEngineOrder.orderBaseAsset.actualSize.value * tradingEngineOrder.rate.value
|
||||
@@ -133,7 +133,7 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
tradingEngineOrder.orderStatistics.actualRate.value = TS.projects.foundations.utilities.miscellaneousFunctions.truncateToThisPrecision(tradingEngineOrder.orderStatistics.actualRate.value, 10)
|
||||
|
||||
/*
|
||||
If the Actual Rate happens to be exctly the same than the order rate, then there is
|
||||
If the Actual Rate happens to be exactly the same than the order rate, then there is
|
||||
nothing else to do here. Otherwise there are adjustments to be made.
|
||||
*/
|
||||
if (tradingEngineOrder.orderStatistics.actualRate.value === tradingEngineOrder.rate.value) { return }
|
||||
@@ -146,12 +146,12 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
function recalculateActualSize() {
|
||||
/*
|
||||
Now we know the Actual Rate at which the order was filled. Since the actual rate
|
||||
is not the same as the Rate we defined for the order, we need to syncronize
|
||||
is not the same as the Rate we defined for the order, we need to synchronize
|
||||
the Actual Order Size for Quoted Asset since it was calculated with the Order Size that we
|
||||
now know it is not the one really used at the exchange. We will recalculate the
|
||||
Actual Size in Quoted Asset and not in Base Asset, since the Actual Size in Base Asset
|
||||
is the one we accepted by the exchange, so that is fixed, regardless of how we initially
|
||||
got the Order Size in Base Asset, either from direct imput from the user or calculated
|
||||
got the Order Size in Base Asset, either from direct input from the user or calculated
|
||||
from the Order Size in Quoted Asset input it by the user. So here we go.
|
||||
*/
|
||||
previousQuotedAssetActualSize = tradingEngineOrder.orderQuotedAsset.actualSize.value
|
||||
@@ -270,7 +270,7 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
async function feesPaidCalculation(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, order, applyFeePercentage) {
|
||||
/*
|
||||
Within the order information received from the exchange we can not see the fees paid so we need to
|
||||
calculate them ourselves. Knwowing the Fees Paid is critical to later update the balances correctly,
|
||||
calculate them ourselves. Knowing the Fees Paid is critical to later update the balances correctly,
|
||||
since at every trade we will receive less than just the Actual Size. In fact we will receive the Actual
|
||||
Size minus the Fees Paid.
|
||||
|
||||
@@ -324,7 +324,7 @@ exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processInd
|
||||
/*
|
||||
This calculation is for informational purposes, so that users do not have to calculate
|
||||
it by themselves. The Amount Received out of the trade depends if we are Buying or Selling
|
||||
the Base Asset. If we are Buying, then the Amount Receiced will be in Base Asset. If we
|
||||
the Base Asset. If we are Buying, then the Amount Received will be in Base Asset. If we
|
||||
are selling then it will be in Quoted Asset.
|
||||
*/
|
||||
|
||||
|
||||
+6
-6
@@ -36,7 +36,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
async function actualSizeSimulation(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, applyFeePercentage) {
|
||||
/*
|
||||
The Actual Size is the size the exchange accepts for the order,
|
||||
regarless of the size sent in the request to the exchange.
|
||||
regardless of the size sent in the request to the exchange.
|
||||
|
||||
While backtesting and paper trading, we do not really need to
|
||||
simulate an Actual Size. We will just copy to that field the
|
||||
@@ -81,7 +81,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
switch (tradingEngineOrder.type) {
|
||||
case 'Market Order': {
|
||||
|
||||
/* Actual Rate is simulated based on the Session Paremeters */
|
||||
/* Actual Rate is simulated based on the Session Parameters */
|
||||
let slippageAmount = tradingEngineOrder.rate.value * sessionParameters.slippage.config.marketOrderRate / 100
|
||||
if (slippageAmount !== 0) {
|
||||
switch (tradingSystemOrder.type) {
|
||||
@@ -197,7 +197,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
Until here we have got the Actual Rate based on the formula definition or based on session parameters slippage.
|
||||
The last check is about watching what happened in the market. Let's remember that the exchange will
|
||||
fill the order with the best possible matches at it's order book. That means that if the rate
|
||||
we set for the order was too low (for a sale order) or too hight (for a buy order), the actual rate
|
||||
we set for the order was too low (for a sale order) or too height (for a buy order), the actual rate
|
||||
should be better than expected.
|
||||
|
||||
We don't know what it is at the order book, but whe know that the last candle includes trades that bounced between
|
||||
@@ -303,7 +303,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
if (tradingEngineOrder.orderStatistics.actualRate.value === tradingEngineOrder.rate.value) { return }
|
||||
/*
|
||||
Since the Actual Rate might have changed, we need to recalculate the Size Placed, where we accumulate all the Size Placed of
|
||||
all orders of a Stage. For Base Asset there is nothing to do, since the Actual Rate does not have an inpact on it.
|
||||
all orders of a Stage. For Base Asset there is nothing to do, since the Actual Rate does not have an impact on it.
|
||||
|
||||
For Quoted Asset, we need to first unaccount what this same orded added before to Size Placed (with the precious Actual Size) and
|
||||
account with the new Actual Size.
|
||||
@@ -462,7 +462,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
}
|
||||
|
||||
/*
|
||||
Another way to simulate the Fees Paid is by using the Session Paremeters configuration for Fees.
|
||||
Another way to simulate the Fees Paid is by using the Session Parameters configuration for Fees.
|
||||
*/
|
||||
switch (tradingEngineOrder.type) {
|
||||
case 'Market Order': {
|
||||
@@ -510,7 +510,7 @@ exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processInde
|
||||
/*
|
||||
This simulation is for informational purposes, so that users do not have to calculate
|
||||
it by themselves. The Amount Received out of the trade depends if we are Buying or Selling
|
||||
the Base Asset. If we are Buying, then the Amount Receiced will be in Base Asset. If we
|
||||
the Base Asset. If we are Buying, then the Amount Received will be in Base Asset. If we
|
||||
are selling then it will be in Quoted Asset.
|
||||
*/
|
||||
|
||||
|
||||
+4
-4
@@ -135,7 +135,7 @@ exports.newAlgorithmicTradingBotModulesSnapshots = function(processIndex) {
|
||||
function evalNode(node) {
|
||||
if (node === undefined) { return }
|
||||
|
||||
/* Here we check if there is a codition to be evaluated */
|
||||
/* Here we check if there is a condition to be evaluated */
|
||||
if (node.type === 'Condition') {
|
||||
/* We will eval this condition */
|
||||
evalCondition(node)
|
||||
@@ -154,7 +154,7 @@ exports.newAlgorithmicTradingBotModulesSnapshots = function(processIndex) {
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
if (schemaDocument.childrenNodesProperties !== 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.
|
||||
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 avoid counting each property of those as individual children.
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
@@ -398,7 +398,7 @@ exports.newAlgorithmicTradingBotModulesSnapshots = function(processIndex) {
|
||||
if (record[record.length - 1] === undefined && contentArray.length > 0) {
|
||||
|
||||
let rowToMutateArray = contentArray[contentArray.length - 1].split(',')
|
||||
// check if are for sure on the same tradenumber and merge the data and remove previous line incl separator
|
||||
// check if are for sure on the same trade number and merge the data and remove previous line incl separator
|
||||
if (rowToMutateArray[0] == record[0]) {
|
||||
record.pop()
|
||||
rowToMutateArray.splice(0, record.length)
|
||||
@@ -451,7 +451,7 @@ exports.newAlgorithmicTradingBotModulesSnapshots = function(processIndex) {
|
||||
function onFileReceived(err, text) {
|
||||
if (err.result === TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
|
||||
try {
|
||||
// remove the last linebreak and seperator which is introduced extra during save
|
||||
// remove the last linebreak and separator which is introduced extra during save
|
||||
text = text.replace(/\n$/, '')
|
||||
text = text.replace(/\r\n$/, '')
|
||||
writeOutput(text)
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
|
||||
/*
|
||||
We call the Trading Engine to the data structure that is needed in order to exevute the
|
||||
We call the Trading Engine to the data structure that is needed in order to execute the
|
||||
trading protocol with the specific rules defined at the Trading System.
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,7 @@ exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
|
||||
|
||||
if (TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_FIRST_LOOP === true) {
|
||||
/*
|
||||
Here we will go through all the nodes in the Trading Engine hiriarchy and
|
||||
Here we will go through all the nodes in the Trading Engine hierarchy and
|
||||
apply the initial value to the value property when needed
|
||||
*/
|
||||
initializeNode(tradingEngine)
|
||||
@@ -116,7 +116,7 @@ exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
if (schemaDocument.childrenNodesProperties !== 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.
|
||||
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 avoid counting each property of those as individual children.
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
@@ -155,7 +155,7 @@ exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
if (schemaDocument.childrenNodesProperties !== 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.
|
||||
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 avoid counting each property of those as individual children.
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
@@ -198,7 +198,7 @@ exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
if (schemaDocument.childrenNodesProperties !== 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.
|
||||
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 avoid counting each property of those as individual children.
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
|
||||
+2
-2
@@ -108,7 +108,7 @@ exports.newAlgorithmicTradingBotModulesTradingEpisode = function (processIndex)
|
||||
|
||||
function updateStatistics() {
|
||||
|
||||
/* Daus Calculation */
|
||||
/* Days Calculation */
|
||||
tradingEngine.tradingCurrent.tradingEpisode.tradingEpisodeStatistics.days.value =
|
||||
tradingEngine.tradingCurrent.tradingEpisode.tradingEpisodeCounters.periods.value *
|
||||
sessionParameters.timeFrame.config.value /
|
||||
@@ -261,7 +261,7 @@ exports.newAlgorithmicTradingBotModulesTradingEpisode = function (processIndex)
|
||||
}
|
||||
|
||||
function updateDistanceToTradingEventsCounters() {
|
||||
/* Keeping Distance Counters Up-to-date while avoinding counting before the first event happens. */
|
||||
/* Keeping Distance Counters Up-to-date while avoiding counting before the first event happens. */
|
||||
if (
|
||||
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.triggerOn.value > 0
|
||||
) {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
exports.newAlgorithmicTradingBotModulesTradingExecution = function (processIndex) {
|
||||
/*
|
||||
The Trading Execution modules manages the execution nodes and execution algoritms.
|
||||
The Trading Execution modules manages the execution nodes and execution algorithms.
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Execution'
|
||||
|
||||
|
||||
+10
-10
@@ -226,7 +226,7 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
let situationName = await checkOrderEvent(tradingSystemOrder.cancelOrderEvent, tradingSystemOrder, executionAlgorithm, executionNode)
|
||||
if (situationName !== undefined) {
|
||||
|
||||
/* Simulate Order Cancelation, if needed. */
|
||||
/* Simulate Order Cancellation, if needed. */
|
||||
simulateCancelOrder(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, 'Cancel Event')
|
||||
|
||||
/* Cancel the order at the Exchange, if needed. */
|
||||
@@ -731,8 +731,8 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
/* Close this Order */
|
||||
tradingEngineOrder.status.value = 'Closed'
|
||||
/*
|
||||
We must be carefull here not to overide an already defined exitType. It can happen
|
||||
for instance that the order was cancellerd from the but veryfing the cancellation
|
||||
We must be carefully here not to override an already defined exitType. It can happen
|
||||
for instance that the order was cancelled from the but verifying the cancellation
|
||||
was not possible because of a connection to the exchange problem. In that case
|
||||
the exit type was defined but the order was kept open until the verification could be done.
|
||||
*/
|
||||
@@ -764,7 +764,7 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
}
|
||||
|
||||
/*
|
||||
If the order happens to be at least partially filled, there is a syncronization work
|
||||
If the order happens to be at least partially filled, there is a synchronization work
|
||||
we need to do, that includes discovering which is the Actual Rate the order is being filled,
|
||||
the Fees Paid and many other thing we need to account for.
|
||||
*/
|
||||
@@ -1118,7 +1118,7 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
if (order.status === 'NotFound') {
|
||||
/*
|
||||
Some exchanges, like Coinbase Pro, deletes orders after being cancelled, and when we request information
|
||||
about them, it returns null. We will interprate this as ORDER NOT FOUND.
|
||||
about them, it returns null. We will interpret this as ORDER NOT FOUND.
|
||||
*/
|
||||
const message = 'Order Not Found at the Exchange'
|
||||
let docs = {
|
||||
@@ -1136,8 +1136,8 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
]
|
||||
)
|
||||
/*
|
||||
We must be carefull here not to overide an already defined exitType. It can happen
|
||||
for instance that the order was cancellerd from the but veryfing the cancellation
|
||||
We must be carefully here not to overide an already defined exitType. It can happen
|
||||
for instance that the order was cancelled from the but verifying the cancellation
|
||||
was not possible because of a connection to the exchange problem. In that case
|
||||
the exit type was defined but the order was kept open until the verification could be done.
|
||||
*/
|
||||
@@ -1148,7 +1148,7 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
|
||||
/*
|
||||
Close this Order. Note that we are not closing the order until we have the exchange
|
||||
response with the order details that we can use to syncronize with our accoounting.
|
||||
response with the order details that we can use to synchronize with our accounting.
|
||||
Otherwise if the connection to the exchange fails, we would have a closed order not
|
||||
accounted in any way.
|
||||
*/
|
||||
@@ -1182,8 +1182,8 @@ exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
|
||||
async function recalculateStageSize(tradingEngineStage, tradingEngineOrder) {
|
||||
/*
|
||||
Since the order is Cancelled, we need to adjust the stage sizePlaced. Remember that the Stage
|
||||
Size Placed accumulates for each asset, the order size placed at the exchange. A cancelation means that
|
||||
only the part filled can be considered placed, so we need to substract from the stage size
|
||||
Size Placed accumulates for each asset, the order size placed at the exchange. A cancellation means that
|
||||
only the part filled can be considered placed, so we need to subtract from the stage size
|
||||
the remainder. To achieve this with the information we currently have, we are going first
|
||||
to unaccount the order actual size, and the account only the sizeFilled + the feesPaid.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
exports.newAlgorithmicTradingBotModulesTradingOutput = function (processIndex) {
|
||||
/*
|
||||
This module will load if necesary all the data outputs so that they can be appended with new
|
||||
This module will load if necessary 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'
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ exports.newAlgorithmicTradingBotModulesTradingPosition = function (processIndex)
|
||||
/* Updating Episode Counters */
|
||||
tradingEngine.tradingCurrent.tradingEpisode.tradingEpisodeCounters.positions.value++
|
||||
|
||||
/* Inicializing this counter */
|
||||
/* Initializing this counter */
|
||||
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.takePosition.value = 1
|
||||
|
||||
/* Remember the balance we had before taking the position to later calculate profit or loss */
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@
|
||||
This is the Date that is going to be used across the execution of this Trading Process.
|
||||
We need this because it has a different life cycle than the processData stored at the
|
||||
Trading Engine data structure. This date has to remain the same during the whole execution
|
||||
of the Trading Process until the end, inclusind the writing of Data Ranges and Status Reports.
|
||||
of the Trading Process until the end, including the writing of Data Ranges and Status Reports.
|
||||
The processDate of the Trading Engine data structure on the other hand can be changed during
|
||||
the simulation loop, once we discover that all candles from a certain date have benn processed.
|
||||
Here is the point where we sync one and the other.
|
||||
@@ -108,7 +108,7 @@
|
||||
Here we check if we need to get Daily Files or not. As an optimization, when
|
||||
we are running on a Time Frame of 1hs or above, we are not going to load
|
||||
dependencies on Daily Files. The way we recognize that is by checking if
|
||||
we alreaady set a value to currentTimeFrame.value. We are also not going to loop
|
||||
we already set a value to currentTimeFrame.value. We are also not going to loop
|
||||
through days if we are processing market files.
|
||||
*/
|
||||
if (currentTimeFrame.value) {
|
||||
|
||||
+10
-10
@@ -95,14 +95,14 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
*/
|
||||
for (let index = 0; index < productRoot.length; index++) {
|
||||
/*
|
||||
The Product Root Node is the root of the node hiriarchy from where we are going to extract the record values.
|
||||
The Product Root Node is the root of the node hierarchy from where we are going to extract the record values.
|
||||
*/
|
||||
let productRootNode = productRoot[index]
|
||||
let record = scanRecordDefinition(product, productRootNode, index)
|
||||
if (record !== undefined) {
|
||||
/*
|
||||
We will add the index value to the record itself, so that the plotter can know to which
|
||||
brach of the trading engine data structure it belongs.
|
||||
branch of the trading engine data structure it belongs.
|
||||
*/
|
||||
record.push(index)
|
||||
persistIndividualRecord(record, product, outputDatasetArray)
|
||||
@@ -114,7 +114,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
the record to be saved at the output file.
|
||||
*/
|
||||
/*
|
||||
The Product Root Node is the root of the node hiriarchy from where we are going to extract the record values.
|
||||
The Product Root Node is the root of the node hierarchy from where we are going to extract the record values.
|
||||
*/
|
||||
let productRootNode = productRoot
|
||||
let record = scanRecordDefinition(product, productRootNode)
|
||||
@@ -131,7 +131,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
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
|
||||
The Property Root Node is the Root of the Hierarchy 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
|
||||
@@ -150,7 +150,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
}
|
||||
}
|
||||
/*
|
||||
The Target Node is the node from where we are going to exctract the value.
|
||||
The Target Node is the node from where we are going to extract the value.
|
||||
We will use the codeName of the Record Property to match it with
|
||||
any of the properties of the Root Node to get the Target Node.
|
||||
*/
|
||||
@@ -170,7 +170,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
targetNode = propertyRootNode[recordProperty.config.childProperty]
|
||||
}
|
||||
/*
|
||||
It can happen that intead of having a Node in targetNode what we have is an
|
||||
It can happen that instead 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.
|
||||
*/
|
||||
@@ -187,7 +187,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
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 = 0 // This is a default value, since we do not want null in files because it breakes JSON format.
|
||||
let value = 0 // This is a default value, since we do not want null in files because it brakes JSON format.
|
||||
if (targetNode !== undefined) {
|
||||
if (targetNode.type !== undefined) {
|
||||
/*
|
||||
@@ -251,14 +251,14 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
/*
|
||||
When dealing with Daily Files, we need to avoid to write an open object at the last 'candle' of the day,
|
||||
since the object will be duplicated on the next day. How do we know we are positioned at the last candle
|
||||
of the day? Easy: the end of the candle must be 1 millisecod before the next day. That happens at any
|
||||
of the day? Easy: the end of the candle must be 1 millisecond before the next day. That happens at any
|
||||
time frame.
|
||||
*/
|
||||
let currentDay = new Date(tradingEngine.tradingCurrent.tradingEpisode.candle.end.value)
|
||||
let nextDay = new Date(tradingEngine.tradingCurrent.tradingEpisode.candle.end.value + 1)
|
||||
if (currentDay.getUTCDate() !== nextDay.getUTCDate()) {
|
||||
/*
|
||||
We will save the object only if it is closed, becasuse we are at the last candle of the day.
|
||||
We will save the object only if it is closed, because we are at the last candle of the day.
|
||||
*/
|
||||
if (propertyValue === product.config.propertyValueThatClosesObject) {
|
||||
outputDatasetArray.push(record)
|
||||
@@ -275,7 +275,7 @@ exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex)
|
||||
}
|
||||
else {
|
||||
/*
|
||||
For Market Files we will add a record everytime that proeprty value does not match this
|
||||
For Market Files we will add a record everytime that property value does not match this
|
||||
*/
|
||||
if (propertyValue !== product.config.propertyValueThatPreventsSavingObject) {
|
||||
outputDatasetArray.push(record)
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processIndex) {
|
||||
/*
|
||||
This Module represents the trading simulacion. Escentially a loop through a set of candles and
|
||||
This Module represents the trading simulation. Essentially a loop through a set of candles and
|
||||
the execution at each loop cycle of the Trading System Protocol.
|
||||
*/
|
||||
const MODULE_NAME = 'Trading Simulation -> ' + TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].session.name
|
||||
@@ -134,7 +134,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
|
||||
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.setCurrentCandle(candle) // We move the current candle we are standing at, to the trading engine data structure to make it available to anyone, including conditions and formulas.
|
||||
|
||||
/* We emit a heart beat so that the UI can now where we are at the overal process.*/
|
||||
/* We emit a heart beat so that the UI can now where we are at the overall process.*/
|
||||
heartBeat()
|
||||
|
||||
/* Opening the Episode, if needed. */
|
||||
@@ -157,7 +157,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
|
||||
/*
|
||||
Do the stuff needed previous to the run like
|
||||
Episode Counters and Statistics update. Mantaince is done
|
||||
Episode Counters and Statistics update. Maintenance is done
|
||||
once per simulation candle.
|
||||
*/
|
||||
tradingSystemModuleObject.mantain()
|
||||
@@ -176,7 +176,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
|
||||
/*
|
||||
We check if we need to stop before appending the records so that the stop
|
||||
reason is also propery recorded. Note also that we check this after the first
|
||||
reason is also properly recorded. Note also that we check this after the first
|
||||
cycle, where orders have not been submitted to the exchange yet, but we
|
||||
had the chance to check for the status of placed orders or even cancel
|
||||
the ones that needed cancellation.
|
||||
@@ -312,7 +312,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
let currentDate = new Date(heartBeatDate)
|
||||
let percentage = TS.projects.foundations.utilities.dateTimeFunctions.getPercentage(fromDate, currentDate, lastDate)
|
||||
/*
|
||||
Theere are a few tasks that we need to do only when the date changes,
|
||||
There are a few tasks that we need to do only when the date changes,
|
||||
otherwise it would be suboptimal.
|
||||
*/
|
||||
if (heartBeatDate.valueOf() !== previousHeartBeatDate) {
|
||||
@@ -328,7 +328,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newInternalLoop(currentDate, percentage)
|
||||
}
|
||||
|
||||
/* Date only hearbeat */
|
||||
/* Date only heartbeat */
|
||||
if (sessionParameters.heartbeats.config.date === true && sessionParameters.heartbeats.config.candleIndex === false) {
|
||||
hartbeatText = hartbeatText + currentDateString
|
||||
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex, hartbeatText, percentage)
|
||||
@@ -337,7 +337,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
}
|
||||
|
||||
/*
|
||||
When the Candle Index nees to be shown, then we can not send the hearbet
|
||||
When the Candle Index needs to be shown, then we can not send the heartbeat
|
||||
only when the dates changes, we have to send it for every candle.
|
||||
It might also contain the date information.
|
||||
*/
|
||||
@@ -354,7 +354,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
|
||||
function positionDataStructuresAtCurrentCandle() {
|
||||
/*
|
||||
In conditions and Formulas, we want users to have an easy sintax to refer to indicators. In order to achieve that, we need the user to have
|
||||
In conditions and Formulas, we want users to have an easy syntax to refer to indicators. In order to achieve that, we need the user to have
|
||||
easy access to the current candle for instance, or the current bollinger band, meaning the one the Simulation is currently standing at.
|
||||
For that reason we do the following processing, to have at the chart data structure the current objects of each indicator / time frame.
|
||||
*/
|
||||
@@ -483,7 +483,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
Note: for Daily Files, this means that the last candle of each day will never be processed.
|
||||
|
||||
The first +1 is because array indexes are based on 0.
|
||||
The second +1 is because we need to compare the next candle (remember that the loops allways avoid the
|
||||
The second +1 is because we need to compare the next candle (remember that the loops always avoid the
|
||||
last candle of the dataset available.)
|
||||
*/
|
||||
if (tradingEngine.tradingCurrent.tradingEpisode.candle.index.value + 1 + 1 === candles.length) {
|
||||
@@ -550,7 +550,7 @@ exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processInde
|
||||
}
|
||||
|
||||
function checkMinimunAndMaximunBalance() {
|
||||
/* Checks for Minimun and Maximun Balance. We do the check while not inside any strategy only. */
|
||||
/* Checks for Minimum and Maximum Balance. We do the check while not inside any strategy only. */
|
||||
if (
|
||||
tradingEngine.tradingCurrent.strategy.index.value === tradingEngine.tradingCurrent.strategy.index.config.initialValue
|
||||
) {
|
||||
|
||||
+9
-9
@@ -422,7 +422,7 @@ exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
|
||||
|
||||
/*
|
||||
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
|
||||
Here we are going to see if that is the case and if it is, we will immediately consider
|
||||
the Manage Stage as closed.
|
||||
*/
|
||||
if (manageStage === undefined) {
|
||||
@@ -820,7 +820,7 @@ exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
|
||||
if (tradingEngine.tradingCurrent.strategyCloseStage.status.value === 'Opening') {
|
||||
/*
|
||||
The system allows the user not to define a close stage, because the close stage is optional.
|
||||
Here we are goint to see if that is the case and if it is, we will inmidiatelly consider
|
||||
Here we are going to see if that is the case and if it is, we will immediately consider
|
||||
the close stage as closed.
|
||||
*/
|
||||
if (tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].closeStage === undefined) {
|
||||
@@ -1024,7 +1024,7 @@ exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
|
||||
The Target Size is defined by the end user either in Base Asset or Quoted Asset.
|
||||
Whatever the user chooses defines also the way we check if the Target was met.
|
||||
Why? Because the counterparty target is estimated with the Target Rate and it
|
||||
is not syncronized with the reality we later learn when the exchange tell us the
|
||||
is not synchronized with the reality we later learn when the exchange tell us the
|
||||
actual rate each of the orders where executed at.
|
||||
|
||||
For the same reason that the user does not know exactly which is the rate the orders
|
||||
@@ -1041,7 +1041,7 @@ exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
|
||||
}
|
||||
/*
|
||||
We will also implement a mechanism to allow users declare an absolute value to add
|
||||
to the Size Filled before checking it againt the Stage Target Size.
|
||||
to the Size Filled before checking it against the Stage Target Size.
|
||||
*/
|
||||
let ABSOLUTE_DUST_IN_BASE_ASSET = 0
|
||||
if (tradingSystemStage.config.absoluteDustInBaseAsset !== undefined) {
|
||||
@@ -1151,13 +1151,13 @@ exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
|
||||
}
|
||||
|
||||
/*
|
||||
The way the begining and end of the Stages object works is as follows:
|
||||
This object begins with the last cycle, that is the current cycle diplaced
|
||||
The way the beginning and end of the Stages object works is as follows:
|
||||
This object begins with the last cycle, that is the current cycle displayed
|
||||
backwards to the current candle. And it ends at the end of the last cycle.
|
||||
During mantainance, we add the time frame of the candle, since we assume it
|
||||
During maintenance, we add the time frame of the candle, since we assume it
|
||||
will survive the 2 cycles without the end being updated. If it closes,
|
||||
then we update the end to the end of the last cycle, overrinding the
|
||||
mantainance if needed. If we assume that in the same cycle there will be
|
||||
then we update the end to the end of the last cycle, overriding the
|
||||
maintenance if needed. If we assume that in the same cycle there will be
|
||||
no closing and opening of the same type of object, then there can be no
|
||||
overlap.
|
||||
*/
|
||||
|
||||
+4
-4
@@ -221,7 +221,7 @@ exports.newAlgorithmicTradingBotModulesTradingSystem = function (processIndex) {
|
||||
|
||||
} catch (err) {
|
||||
/*
|
||||
If an error ocurred during execution, it was alreeady logged and
|
||||
If an error occurred during execution, it was already 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.
|
||||
*/
|
||||
@@ -237,14 +237,14 @@ exports.newAlgorithmicTradingBotModulesTradingSystem = function (processIndex) {
|
||||
function evalNode(node, evaluating, descendentOfNodeType, isDescendent) {
|
||||
if (node === undefined) { return }
|
||||
|
||||
/* Verify if this node is decendent of the specified node type */
|
||||
/* Verify if this node is descendent of the specified node type */
|
||||
if (isDescendent !== true) {
|
||||
if (node.type === descendentOfNodeType) {
|
||||
isDescendent = true
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we check if there is a codition to be evaluated */
|
||||
/* Here we check if there is a condition to be evaluated */
|
||||
if (node.type === 'Condition' && evaluating === 'Conditions') {
|
||||
/* We will eval this condition */
|
||||
if (isDescendent === true) {
|
||||
@@ -276,7 +276,7 @@ exports.newAlgorithmicTradingBotModulesTradingSystem = function (processIndex) {
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
if (schemaDocument.childrenNodesProperties !== 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.
|
||||
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 avoid counting each property of those as individual children.
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
/* We tell the UI that we are running. */
|
||||
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex, undefined, undefined, "Running...")
|
||||
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infrastructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistently all over the execution.
|
||||
|
||||
/* Main Loop Console Logging */
|
||||
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newMainLoop()
|
||||
@@ -95,7 +95,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
|
||||
/* We will prepare first the infrastructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
|
||||
|
||||
let processExecutionEvents
|
||||
let userBot;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return;
|
||||
}
|
||||
/*
|
||||
We will store here the session key, which we will need everytine
|
||||
We will store here the session key, which we will need everytime
|
||||
we need to emit an event related to the session itself.
|
||||
*/
|
||||
let VARIABLES_BY_PROCESS_INDEX = TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex)
|
||||
@@ -109,7 +109,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
/* We are going to initialize here these constants whose values are comming at the event. */
|
||||
/* We are going to initialize here these constants whose values are coming at the event. */
|
||||
TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_SYSTEM_NODE = JSON.parse(message.event.tradingSystem)
|
||||
TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_NODE = JSON.parse(message.event.tradingEngine)
|
||||
TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE = JSON.parse(message.event.session)
|
||||
|
||||
@@ -13,6 +13,17 @@
|
||||
"actionFunction": "payload.executeAction",
|
||||
"actionProject": "Community-Plugins"
|
||||
},
|
||||
{
|
||||
"action": "Add Specified Plugin Data Mine",
|
||||
"label": "Add Specified Plugin Data Mine",
|
||||
"iconPathOn": "data-mine",
|
||||
"iconPathOff": "data-mine",
|
||||
"iconProject": "Data-Mining",
|
||||
"actionProject": "Community-Plugins",
|
||||
"relatedUiObject": "Data Mine",
|
||||
"dontShowAtFullscreen": true,
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Visual-Scripting",
|
||||
@@ -27,6 +38,9 @@
|
||||
"addLeftIcons": true,
|
||||
"level": 1,
|
||||
"propertyNameAtParent": "pluginDataMines",
|
||||
"editors": {
|
||||
"list": true
|
||||
},
|
||||
"attachingRules": {
|
||||
"compatibleTypes": "->Plugin Project->"
|
||||
},
|
||||
|
||||
@@ -12,6 +12,17 @@
|
||||
"actionProject": "Governance",
|
||||
"relatedUiObjectProject": "Governance"
|
||||
},
|
||||
{
|
||||
"action": "Add Specified User Profile",
|
||||
"label": "Add Specified User Profile",
|
||||
"iconPathOn": "user-profile",
|
||||
"iconPathOff": "user-profile",
|
||||
"iconProject": "Governance",
|
||||
"actionProject": "Governance",
|
||||
"relatedUiObject": "User Profile",
|
||||
"dontShowAtFullscreen": true,
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Visual-Scripting",
|
||||
@@ -30,6 +41,9 @@
|
||||
"attachingRules": {
|
||||
"compatibleTypes": "->Plugin Project->"
|
||||
},
|
||||
"editors": {
|
||||
"list": true
|
||||
},
|
||||
"childrenNodesProperties": [
|
||||
{
|
||||
"name": "pluginFiles",
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"type": "Plugins",
|
||||
"definition": {
|
||||
"text": "The plugins hierarchy defines which plugins are to be included in the current workspace. In the context of this hierarchy, plugins are JSON files featuring the description of a hierarchy such as a data mine, trading mine, trading engine, or trading system.",
|
||||
"translations": [
|
||||
{
|
||||
"language": "ES",
|
||||
"text": "The plugins hierarchy define cual plugins se incluirán en el actual workspace. En el contexto de esta jerarquía, plugins son archivos JSON con la descripción de una jerarquía como un data mine, trading mine, trading engine, o trading system.",
|
||||
"updated": 1628037249031
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Иерархия плагинов определяет, какие плагины должны быть включены в текущую рабочую область. В контексте этой иерархии плагины представляют собой файлы JSON, содержащие описание иерархии, такой как шахта данных, торговая шахта, торговый механизм или торговая система.",
|
||||
"updated": 1636194488881
|
||||
}
|
||||
]
|
||||
},
|
||||
"paragraphs": [
|
||||
{
|
||||
"style": "Block",
|
||||
"text": "Content"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "In the context of a community-driven project, a plugin is a device that serves to distribute community-generated intelligence. The project distributes several plugins contributed by the community."
|
||||
},
|
||||
{
|
||||
"style": "Important",
|
||||
"text": "Hierarchies included in the workspace as plugins are not saved at the workspace level. As such, changes made in those hierarchies do not persist. If you wish to modify a plugin and keep working with the modified version in the future, you must either clone or backup the plugin and work on the resulting copy instead.",
|
||||
"updated": 1609866745275
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -38,6 +38,11 @@ function newCommunityPluginsActionSwitch() {
|
||||
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginDataMines(action.node, action.rootNodes)
|
||||
}
|
||||
break
|
||||
case 'Add Specified Plugin Data Mine':
|
||||
{
|
||||
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addSpecifiedPluginDataMine(action.node, action.rootNodes)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Plugin Trading Mines':
|
||||
{
|
||||
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTradingMines(action.node, action.rootNodes)
|
||||
|
||||
@@ -3,6 +3,7 @@ function newPluginsFunctionLibraryPluginsFunctions() {
|
||||
addMissingPluginProjects: addMissingPluginProjects,
|
||||
addMissingPluginTypes: addMissingPluginTypes,
|
||||
addMissingPluginDataMines: addMissingPluginDataMines,
|
||||
addSpecifiedPluginDataMine: addSpecifiedPluginDataMine,
|
||||
addMissingPluginTradingMines: addMissingPluginTradingMines,
|
||||
addMissingPluginTradingSystems: addMissingPluginTradingSystems,
|
||||
addMissingPluginTradingEngines: addMissingPluginTradingEngines,
|
||||
@@ -65,6 +66,32 @@ function newPluginsFunctionLibraryPluginsFunctions() {
|
||||
}
|
||||
}
|
||||
|
||||
function addSpecifiedPluginDataMine(node, rootNodes) {
|
||||
let action = { node: node }
|
||||
|
||||
let projectName = UI.projects.communityPlugins.utilities.plugins.getProjectName(node)
|
||||
if (projectName === "" || projectName === undefined) {
|
||||
if (node.payload.parentNode !== undefined) {
|
||||
node.payload.parentNode.payload.uiObject.setErrorMessage("Config codeName must have the name of the project.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Data-Mines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
let eventSubscriptionId = node.payload.uiObject.container.eventHandler.listenToEvent('listSelectorClicked', onListSelect)
|
||||
node.payload.uiObject.listSelector.activate(action, fileNames, eventSubscriptionId)
|
||||
|
||||
function onListSelect(event) {
|
||||
let selectedArray = []
|
||||
selectedArray.push(event.selectedNode)
|
||||
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, selectedArray, 'Data-Mines', 'Data Mine', 'Data-Mining')
|
||||
node.payload.uiObject.container.eventHandler.stopListening('listSelectorClicked')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMissingPluginTradingMines(node, rootNodes) {
|
||||
let projectName = UI.projects.communityPlugins.utilities.plugins.getProjectName(node)
|
||||
if (projectName === "" || projectName === undefined) {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1 +1 @@
|
||||
{"type":"Data Mine","name":"Zeus","config":"{ \n\"codeName\": \"Zeus\"\n}","project":"Superalgos","sensorBots":[],"apiDataFetcherBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"Super Trend","config":"{ \n\"codeName\": \"Super-Trend\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Time-Frame-Market","config":" {\n \"codeName\": \"Multi-Time-Frame-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Time-Frame-Market\"\n }\n }","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Time-Frame-Market Super Trend","project":"Superalgos","id":"2412939e-1585-47f9-8d09-7ea8dd7c8bf0","savedPayload":{"position":{"x":34664.87658172835,"y":17409.843880743556},"targetPosition":{"x":34703.69943849373,"y":17554.732754686916},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Time-Frame-Market","id":"7c8e7a6f-99c8-4d90-9f44-e3e9e909eb88"}}}],"outputDatasetFolders":[],"id":"74212c63-4a69-407d-80ec-d39ee2d8df74","savedPayload":{"position":{"x":34703.69943849373,"y":17554.732754686916},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"5a35d0d1-cfed-4893-84ab-344a77c7d252","savedPayload":{"position":{"x":34670.168008789864,"y":17150.036259608223},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"25f05344-3e7f-4d5f-ab1c-d72689a85764"}}},{"type":"Status Dependency","name":"","config":"{ \n\"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"2a42dd15-1e04-4826-bd5f-85d95fbae135","savedPayload":{"position":{"x":34897.81372232062,"y":17120.066132856835},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Time-Frame-Market","project":"Superalgos","id":"88a45f27-a0b8-4234-b7aa-f139400305db","savedPayload":{"position":{"x":35079.9756299252,"y":17259.843880743556},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Time-Frame-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"eef38121-80a2-4471-b909-24acdc4d213a","savedPayload":{"position":{"x":34820.168008789864,"y":17409.843880743556},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"25f05344-3e7f-4d5f-ab1c-d72689a85764","savedPayload":{"position":{"x":34954.65432961507,"y":17487.489594274313},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"","project":"Superalgos","id":"d9b0ffbd-c1bd-4e43-a00d-04a6b6fb470b","savedPayload":{"position":{"x":35032.30004314583,"y":17621.97591509952},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"d405bfe9-74f9-4419-8288-94229c9813a6","savedPayload":{"position":{"x":35032.300043145Line truncated
|
||||
{"type":"Data Mine","name":"Zeus","config":"{ \n\"codeName\": \"Zeus\"\n}","project":"Superalgos","sensorBots":[],"apiDataFetcherBots":[],"indicatorBots":[{"type":"Indicator Bot","name":"Super Trend","config":"{ \n\"codeName\": \"Super-Trend\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Multi-Time-Frame-Market","config":" {\n \"codeName\": \"Multi-Time-Frame-Market\",\n \"normalWaitTime\": 0,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Multi-Time-Frame-Market\"\n }\n }","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Time-Frame-Market Super Trend","project":"Superalgos","id":"2412939e-1585-47f9-8d09-7ea8dd7c8bf0","savedPayload":{"position":{"x":34664.87658172835,"y":17409.843880743556},"targetPosition":{"x":34703.69943849373,"y":17554.732754686916},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Time-Frame-Market","id":"7c8e7a6f-99c8-4d90-9f44-e3e9e909eb88"}}}],"outputDatasetFolders":[],"id":"74212c63-4a69-407d-80ec-d39ee2d8df74","savedPayload":{"position":{"x":34703.69943849373,"y":17554.732754686916},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","project":"Superalgos","statusDependencies":[{"type":"Status Dependency","name":"","config":"{ \n\"mainUtility\": \"Self Reference\"\n}","project":"Superalgos","id":"5a35d0d1-cfed-4893-84ab-344a77c7d252","savedPayload":{"position":{"x":34670.168008789864,"y":17150.036259608223},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"25f05344-3e7f-4d5f-ab1c-d72689a85764"}}},{"type":"Status Dependency","name":"","config":"{ \n\"mainUtility\": \"Market Ending Point\"\n}","project":"Superalgos","id":"2a42dd15-1e04-4826-bd5f-85d95fbae135","savedPayload":{"position":{"x":34897.81372232062,"y":17120.066132856835},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"a0a61ba9-91cb-4ec7-92fe-134ff079de2d"}}}],"dataDependencies":[{"type":"Data Dependency","name":"Candles Multi-Time-Frame-Market","project":"Superalgos","id":"88a45f27-a0b8-4234-b7aa-f139400305db","savedPayload":{"position":{"x":35079.9756299252,"y":17259.843880743556},"targetPosition":{"x":34820.168008789864,"y":17409.843880743556},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Time-Frame-Market","id":"2b03494a-67d6-47f1-89b6-53fc4c9116a8"}}}],"dataMineDataDependencies":[],"id":"eef38121-80a2-4471-b909-24acdc4d213a","savedPayload":{"position":{"x":34820.168008789864,"y":17409.843880743556},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","project":"Superalgos","id":"25f05344-3e7f-4d5f-ab1c-d72689a85764","savedPayload":{"position":{"x":34954.65432961507,"y":17487.489594274313},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"","project":"Superalgos","id":"d9b0ffbd-c1bd-4e43-a00d-04a6b6fb470b","savedPayload":{"position":{"x":35032.30004314583,"y":17621.97591509952},"targetPosition":{"x":34742.52229525911,"y":17699.621628630277},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"1824fa00-dd30-4cdc-acc0-01c2f29056c5"}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","project":"Superalgos","id":"d405bfe9-74f9-4419-8288-94229c9813a6","savedPayload":{"position":{"x":35032.300043145Line truncated
|
||||
@@ -8,6 +8,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un Data Mine es una jerarquía que contiene definiciones de sensor, bots indicadores, y sus trazadores. Estas definiciones se obtienen del código de dichos bots.",
|
||||
"updated": 1624230241851
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Шахта данных - это иерархия, содержащая определения датчиков и ботов-индикаторов, а также их плоттеров. Эти определения взяты из фактического кода таких ботов.\n",
|
||||
"updated": 1636192911774
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+6
-1
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un indicator bot es un algoritmo que procesa información que otros bots han generado y produce conjuntos de datos elaborados para que otros los consuman.",
|
||||
"updated": 1624496036942
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Бот-индикатор - это алгоритм, который обрабатывает информацию, сгенерированную другими ботами, и создает сложные наборы данных для использования другими.",
|
||||
"updated": 1636192708246
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -42,4 +47,4 @@
|
||||
"text": "codeName is the name of the bot as used within the code of the system."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -82,13 +82,13 @@ exports.newDataMiningBotModulesSingleMarketAPIDataFetcherBot = function (process
|
||||
/* We tell the UI that we are running. */
|
||||
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex)
|
||||
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infrastructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistently all over the execution.
|
||||
|
||||
/* Main Loop Console Logging */
|
||||
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newMainLoop()
|
||||
|
||||
/* We will prepare first the infraestructure needed for the bot to run. There are 4 modules we need to sucessfullly initialize first. */
|
||||
/* We will prepare first the infrastructure needed for the bot to run. There are 4 modules we need to successfully initialize first. */
|
||||
let processExecutionEvents
|
||||
let statusDependencies;
|
||||
let nextWaitTime;
|
||||
|
||||
@@ -79,13 +79,13 @@
|
||||
/* We tell the UI that we are running. */
|
||||
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex)
|
||||
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date() // This will be considered the process date and time, so as to have it consistenly all over the execution.
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infrastructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date() // This will be considered the process date and time, so as to have it consistently all over the execution.
|
||||
|
||||
/* Main Loop Console Logging */
|
||||
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newMainLoop()
|
||||
|
||||
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
|
||||
/* We will prepare first the infrastructure needed for the bot to run. There are 3 modules we need to successfully initialize first. */
|
||||
let processExecutionEvents
|
||||
let processFramework;
|
||||
let statusDependencies;
|
||||
|
||||
@@ -82,13 +82,13 @@
|
||||
/* We tell the UI that we are running. */
|
||||
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex)
|
||||
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
|
||||
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infrastructure and the bot. */
|
||||
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME = new Date(); // This will be considered the process date and time, so as to have it consistently all over the execution.
|
||||
|
||||
/* Main Loop Console Logging */
|
||||
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newMainLoop()
|
||||
|
||||
/* We will prepare first the infraestructure needed for the bot to run. There are 4 modules we need to sucessfullly initialize first. */
|
||||
/* We will prepare first the infrastructure needed for the bot to run. There are 4 modules we need to successfully initialize first. */
|
||||
let processExecutionEvents
|
||||
let statusDependencies;
|
||||
let nextWaitTime;
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
"pageNumber": 1,
|
||||
"type": "Keyboard Shortcut Quick Guide",
|
||||
"definition": {
|
||||
"text": "Superalgos offers a number of keyboard shortcuts to make working with the platform more efficent and user friendly.",
|
||||
"text": "Superalgos offers a number of keyboard shortcuts to make working with the platform more efficient and user friendly.",
|
||||
"updated": 1634909540261
|
||||
},
|
||||
"paragraphs": [
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Here is the current list of all implemented shortcuts and options for customazation:"
|
||||
"text": "Here is the current list of all implemented shortcuts and options for customization:"
|
||||
},
|
||||
{
|
||||
"style": "Subtitle",
|
||||
@@ -109,7 +109,7 @@
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "Display animation preformance: Ctrl + Shift + Alt + F11",
|
||||
"text": "Display animation performance: Ctrl + Shift + Alt + F11",
|
||||
"updated": 1634910183292
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "You can find additional descriptions of how to use your mouse and keybord to navigate the Charting Space and Design Space at the Basic Navigation page.",
|
||||
"text": "You can find additional descriptions of how to use your mouse and keyboard to navigate the Charting Space and Design Space at the Basic Navigation page.",
|
||||
"updated": 1634912820206
|
||||
},
|
||||
{
|
||||
@@ -145,12 +145,12 @@
|
||||
},
|
||||
{
|
||||
"style": "Important",
|
||||
"text": "If any of these keyboard shortucts do not function as expected, please disable any installed browser extentions while using Superalgos as they can override expected functionality.",
|
||||
"text": "If any of these keyboard shortcuts do not function as expected, please disable any installed browser extentions while using Superalgos as they can override expected functionality.",
|
||||
"updated": 1634999290105
|
||||
},
|
||||
{
|
||||
"style": "Success",
|
||||
"text": "In addtion to this, many shortcuts will work without using the Alt key. For example Ctrl + Shift + Key-S. ",
|
||||
"text": "In addition to this, many shortcuts will work without using the Alt key. For example Ctrl + Shift + Key-S. ",
|
||||
"updated": 1634999389000
|
||||
},
|
||||
{
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
function newEducationFunctionLibraryDocsStats() {
|
||||
function newEducationFunctionLibraryDocsStatisticsFunctions() {
|
||||
let thisObject = {
|
||||
printDocsStats: printDocsStats
|
||||
}
|
||||
@@ -23,6 +23,7 @@ function newEducationFunctionLibraryDocsStats() {
|
||||
for (let i = 0; i < UI.projects.education.spaces.docsSpace.searchEngine.docsIndex.length; i++) {
|
||||
documentPage = UI.projects.education.spaces.docsSpace.searchEngine.docsIndex[i]
|
||||
pagesCount += 1
|
||||
let lastValue
|
||||
if (projectStats[documentPage.project] !== undefined) {
|
||||
lastValue = projectStats[documentPage.project]
|
||||
}
|
||||
@@ -68,7 +68,7 @@ function newFoundationsDocsDocumentPage() {
|
||||
let template = {
|
||||
updated: true,
|
||||
type: UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type,
|
||||
definition: { text: "Write the definition for this " + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.category + "." },
|
||||
definition: {text: "Write the definition for this " + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.category + "."},
|
||||
paragraphs: [
|
||||
{
|
||||
style: "Text",
|
||||
@@ -119,7 +119,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
if (UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.nodeId !== undefined) {
|
||||
node = await UI.projects.foundations.spaces.designSpace.workspace.getNodeById(UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.nodeId)
|
||||
}
|
||||
if (node === undefined) { return }
|
||||
if (node === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
node.payload.floatingObject.unCollapseParent()
|
||||
setTimeout(positionAtNode, 0000, node)
|
||||
@@ -147,7 +149,7 @@ function newFoundationsDocsDocumentPage() {
|
||||
|
||||
/* Title */
|
||||
let titleLabel = thisObject.docsSchemaDocument.type
|
||||
HTML = HTML + '<div id="docs-main-title-div" class="docs-title-table"><div class="docs-table-cell"><h2 class="docs-h2" id="' + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type.toLowerCase().replace(' ', '-') + '" > ' + titleLabel + '</h2></div><div id="projectImageDiv" class="docs-image-container"/></div></div>'
|
||||
HTML = HTML + '<div id="docs-main-title-div" class="docs-title-table"><div class="docs-table-cell"><h2 class="docs-h2" id="' + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type.toLowerCase().replace(' ', '-') + '" > ' + titleLabel + '</h2></div><div id="projectImageDiv" class="docs-image-container"/></div></div>'
|
||||
|
||||
if (thisObject.docsSchemaDocument.deleted === true) {
|
||||
let key = 'auto-generated-flag-paragraph'
|
||||
@@ -563,7 +565,8 @@ function newFoundationsDocsDocumentPage() {
|
||||
includedSchemaDocument = SCHEMAS_BY_PROJECT.get(project).map.docsBookSchema.get(type)
|
||||
break
|
||||
}
|
||||
default: return 'Category (' + category + ') is not valid. Use Node, Concept, Topic, Review or Book instead.'
|
||||
default:
|
||||
return 'Category (' + category + ') is not valid. Use Node, Concept, Topic, Review or Book instead.'
|
||||
}
|
||||
if (includedSchemaDocument === undefined) {
|
||||
return category + ' document ' + type + ' not found at project ' + project
|
||||
@@ -642,7 +645,6 @@ function newFoundationsDocsDocumentPage() {
|
||||
let introText = splittedChapterText[4]
|
||||
|
||||
|
||||
|
||||
if (project === undefined || category === undefined || chapterNumber === undefined || chapterName === undefined) {
|
||||
return 'Chapter paragraph style Syntax Error. Some of the required parameters are undefined. Check the Docs Chapter Style Syntax. This error message will disappear as soon as you fix the problem.'
|
||||
}
|
||||
@@ -843,15 +845,20 @@ function newFoundationsDocsDocumentPage() {
|
||||
function addProjectImage() {
|
||||
let imageName = UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.project.toLowerCase().replaceAll(' ', '-')
|
||||
let imageElement = UI.projects.foundations.spaces.designSpace.getIconByProjectAndName(UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.project, imageName)
|
||||
imageElement.width = "50"
|
||||
imageElement.height = "50"
|
||||
if (imageElement !== undefined) {
|
||||
imageElement.width = "50"
|
||||
imageElement.height = "50"
|
||||
|
||||
let projectImageDiv = document.getElementById('projectImageDiv')
|
||||
projectImageDiv.appendChild(imageElement)
|
||||
|
||||
let projectImageDiv = document.getElementById('projectImageDiv')
|
||||
projectImageDiv.appendChild(imageElement)
|
||||
}
|
||||
}
|
||||
|
||||
function addMenuItemsImages() {
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.menuItems === undefined) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.menuItems === undefined) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < appSchemaDocument.menuItems.length; i++) {
|
||||
let menuItem = appSchemaDocument.menuItems[i]
|
||||
let collectionImage = getIcon(appSchemaDocument.menuItems[i].relatedUiObjectProject, appSchemaDocument.menuItems[i].actionProject)
|
||||
@@ -867,7 +874,7 @@ function newFoundationsDocsDocumentPage() {
|
||||
parentElement.replaceChild(imageElement, dummyImage)
|
||||
|
||||
function getIcon(relatedUiObjectProject, actionProject) {
|
||||
let project
|
||||
let project
|
||||
if (menuItem.relatedUiObject !== undefined) {
|
||||
if (relatedUiObjectProject !== undefined) {
|
||||
project = relatedUiObjectProject
|
||||
@@ -892,7 +899,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
}
|
||||
|
||||
function addChildrenNodesPropertiesImages() {
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.childrenNodesProperties === undefined) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.childrenNodesProperties === undefined) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < appSchemaDocument.childrenNodesProperties.length; i++) {
|
||||
let childrenNodesProperty = appSchemaDocument.childrenNodesProperties[i]
|
||||
let collectionImage = getIcon()
|
||||
@@ -918,7 +927,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
}
|
||||
|
||||
function addAttachingAndReferencingRulesImages() {
|
||||
if (appSchemaDocument === undefined) { return }
|
||||
if (appSchemaDocument === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
if (appSchemaDocument.attachingRules !== undefined) {
|
||||
if (appSchemaDocument.attachingRules.compatibleTypes !== undefined) {
|
||||
@@ -944,10 +955,14 @@ function newFoundationsDocsDocumentPage() {
|
||||
function imageForTheseNodes(nodeList, additionToKey) {
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
let listItem = nodeList[i]
|
||||
if (listItem === "") { continue }
|
||||
if (listItem === "") {
|
||||
continue
|
||||
}
|
||||
|
||||
let collectionImage = getIcon()
|
||||
if (collectionImage === undefined) { continue }
|
||||
if (collectionImage === undefined) {
|
||||
continue
|
||||
}
|
||||
let imageElement = collectionImage.cloneNode()
|
||||
|
||||
imageElement.className = "docs-collapsible-image"
|
||||
@@ -971,9 +986,13 @@ function newFoundationsDocsDocumentPage() {
|
||||
}
|
||||
|
||||
function addConfigurationImages() {
|
||||
if (appSchemaDocument === undefined) { return }
|
||||
if (appSchemaDocument === undefined) {
|
||||
return
|
||||
}
|
||||
let configImageElementArray = document.getElementsByClassName('docs-configuration-property-image')
|
||||
if (configImageElementArray === undefined) { return }
|
||||
if (configImageElementArray === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
We need to create our own array otherwise while replacing the childElement
|
||||
@@ -1014,7 +1033,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.menuItems === undefined || appSchemaDocument.menuItems.length === 0) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.menuItems === undefined || appSchemaDocument.menuItems.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
@@ -1054,7 +1075,8 @@ function newFoundationsDocsDocumentPage() {
|
||||
}
|
||||
paragraph = {
|
||||
style: "Success",
|
||||
text: "When a menu item is grayed out, it means that " + appSchemaDocument.type + " already has the required child type that the menu item may add, and only that child is allowed for that case. " }
|
||||
text: "When a menu item is grayed out, it means that " + appSchemaDocument.type + " already has the required child type that the menu item may add, and only that child is allowed for that case. "
|
||||
}
|
||||
renderParagraph(paragraph, key)
|
||||
autoGeneratedParagraphIndex++
|
||||
}
|
||||
@@ -1066,7 +1088,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.childrenNodesProperties === undefined || appSchemaDocument.childrenNodesProperties.length === 0) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.childrenNodesProperties === undefined || appSchemaDocument.childrenNodesProperties.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
@@ -1114,7 +1138,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || (appSchemaDocument.attachingRules === undefined && appSchemaDocument.referencingRules === undefined)) { return }
|
||||
if (appSchemaDocument === undefined || (appSchemaDocument.attachingRules === undefined && appSchemaDocument.referencingRules === undefined)) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
@@ -1157,7 +1183,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
function listAllTheseNodes(nodeList, additionToKey) {
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
let listItem = nodeList[i]
|
||||
if (listItem === "") { continue }
|
||||
if (listItem === "") {
|
||||
continue
|
||||
}
|
||||
HTML = HTML + '<button id="docs-' + additionToKey + '-' + i + '" type="button" class="docs-non-collapsible-element"><img>' + UI.projects.education.utilities.docs.addToolTips(listItem, UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type) + '</button>'
|
||||
}
|
||||
}
|
||||
@@ -1169,7 +1197,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || (appSchemaDocument.referencingRules === undefined && appSchemaDocument.referencingRules === undefined)) { return }
|
||||
if (appSchemaDocument === undefined || (appSchemaDocument.referencingRules === undefined && appSchemaDocument.referencingRules === undefined)) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
@@ -1212,7 +1242,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
function listAllTheseNodes(nodeList, additionToKey) {
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
let listItem = nodeList[i]
|
||||
if (listItem === "") { continue }
|
||||
if (listItem === "") {
|
||||
continue
|
||||
}
|
||||
HTML = HTML + '<button id="docs-' + additionToKey + '-' + i + '" type="button" class="docs-non-collapsible-element"><img>' + UI.projects.education.utilities.docs.addToolTips(listItem, UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type) + '</button>'
|
||||
}
|
||||
}
|
||||
@@ -1224,7 +1256,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.config !== true) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.config !== true) {
|
||||
return
|
||||
}
|
||||
paragraph = {
|
||||
style: "Subtitle",
|
||||
text: "Initial Values"
|
||||
@@ -1232,7 +1266,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
renderParagraph(paragraph, key)
|
||||
autoGeneratedParagraphIndex++
|
||||
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.config === undefined) { return }
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.config === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Text",
|
||||
@@ -1296,6 +1332,7 @@ function newFoundationsDocsDocumentPage() {
|
||||
}
|
||||
/* Third Step: we will display the list of properties and the sample values */
|
||||
propertyMap.forEach(displayProperty)
|
||||
|
||||
function displayProperty(valueArray, mapKey, map) {
|
||||
|
||||
let name = UI.projects.foundations.utilities.strings.fromCamelCaseToUpperWithSpaces(mapKey)
|
||||
@@ -1324,7 +1361,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.code !== true) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.code !== true) {
|
||||
return
|
||||
}
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "" + appSchemaDocument.type + " Code"
|
||||
@@ -1338,7 +1377,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
renderParagraph(paragraph, key)
|
||||
autoGeneratedParagraphIndex++
|
||||
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.code === undefined) { return }
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.code === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Subtitle",
|
||||
@@ -1398,8 +1439,11 @@ function newFoundationsDocsDocumentPage() {
|
||||
/* Third Step: we will display the list of properties and the sample values */
|
||||
let exampleCounter = 1
|
||||
codeMap.forEach(displayProperty)
|
||||
|
||||
function displayProperty(code, mapKey, map) {
|
||||
if (exampleCounter > 10) { return }
|
||||
if (exampleCounter > 10) {
|
||||
return
|
||||
}
|
||||
HTML = HTML + '<button id="docs-code-example-' + exampleCounter + '" type="button" class="docs-collapsible-element">' + 'Example #' + exampleCounter + '</button>'
|
||||
HTML = HTML + '<div class="docs-collapsible-code-content">'
|
||||
exampleCounter++
|
||||
@@ -1420,7 +1464,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
*/
|
||||
let paragraph
|
||||
let key = 'auto-generated-paragraph-' + autoGeneratedParagraphIndex
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.formula !== true) { return }
|
||||
if (appSchemaDocument === undefined || appSchemaDocument.editors === undefined || appSchemaDocument.editors.formula !== true) {
|
||||
return
|
||||
}
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "" + appSchemaDocument.type + " Formula"
|
||||
@@ -1434,7 +1480,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
renderParagraph(paragraph, key)
|
||||
autoGeneratedParagraphIndex++
|
||||
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.code === undefined) { return }
|
||||
if (appSchemaDocument.initialValues === undefined || appSchemaDocument.initialValues.code === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
paragraph = {
|
||||
style: "Subtitle",
|
||||
@@ -1494,8 +1542,11 @@ function newFoundationsDocsDocumentPage() {
|
||||
/* Third Step: we will display the list of properties and the sample values */
|
||||
let exampleCounter = 1
|
||||
codeMap.forEach(displayProperty)
|
||||
|
||||
function displayProperty(code, mapKey, map) {
|
||||
if (exampleCounter > 10) { return }
|
||||
if (exampleCounter > 10) {
|
||||
return
|
||||
}
|
||||
HTML = HTML + '<button id="docs-code-example-' + exampleCounter + '" type="button" class="docs-collapsible-element">' + 'Example #' + exampleCounter + '</button>'
|
||||
HTML = HTML + '<div class="docs-collapsible-code-content">'
|
||||
exampleCounter++
|
||||
@@ -1800,9 +1851,15 @@ function newFoundationsDocsDocumentPage() {
|
||||
let levels = splittedParams[2]
|
||||
|
||||
appSchemaDocument = SCHEMAS_BY_PROJECT.get(project).map.appSchema.get(type)
|
||||
if (appSchemaDocument === undefined) { return }
|
||||
if (isNaN(levels) === true) { return }
|
||||
if (levels > MAX_COLUMNS) { return }
|
||||
if (appSchemaDocument === undefined) {
|
||||
return
|
||||
}
|
||||
if (isNaN(levels) === true) {
|
||||
return
|
||||
}
|
||||
if (levels > MAX_COLUMNS) {
|
||||
return
|
||||
}
|
||||
|
||||
let contentMatrix = []
|
||||
|
||||
@@ -1824,7 +1881,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
|
||||
function scanHierarchy(schemaDocument, project, currentColumn, lastChild) {
|
||||
|
||||
if (schemaDocument === undefined) { return }
|
||||
if (schemaDocument === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
currentRow++
|
||||
|
||||
@@ -1848,7 +1907,9 @@ function newFoundationsDocsDocumentPage() {
|
||||
matrixRow[currentColumn - 1] = FORK
|
||||
}
|
||||
|
||||
if (schemaDocument.childrenNodesProperties === undefined) { return }
|
||||
if (schemaDocument.childrenNodesProperties === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
@@ -2029,7 +2090,8 @@ function newFoundationsDocsDocumentPage() {
|
||||
let collapsibleElementsArray = document.getElementsByClassName("docs-collapsible-element")
|
||||
|
||||
for (let i = 0; i < collapsibleElementsArray.length; i++) {
|
||||
collapsibleElementsArray[i].removeEventListener("click", function () { })
|
||||
collapsibleElementsArray[i].removeEventListener("click", function () {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,12 @@ function newFoundationsDocsFooter() {
|
||||
}
|
||||
HTML = HTML + '"></a>'
|
||||
|
||||
HTML = HTML + '<a href="#" onClick="UI.projects.education.spaces.docsSpace.changeLanguage(\'AR\')"><img src="Images/Languages/AR.png" title="Arabic" class="docs-footer-language'
|
||||
if (languageCode === 'AR') {
|
||||
HTML = HTML + '-selected'
|
||||
}
|
||||
HTML = HTML + '"></a>'
|
||||
|
||||
HTML = HTML + '</div>'
|
||||
|
||||
HTML = HTML + '<div class="docs-footer-cell">'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
function newFoundationsDocsSearchEngine() {
|
||||
let thisObject = {
|
||||
docsIndex: undefined,
|
||||
documentIndex: undefined,
|
||||
setUpSearchEngine: setUpSearchEngine,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
@@ -10,15 +11,28 @@ function newFoundationsDocsSearchEngine() {
|
||||
|
||||
function initialize() {
|
||||
thisObject.docsIndex = []
|
||||
thisObject.documentIndex = new FlexSearch.Document({
|
||||
preset: "performance",
|
||||
worker: true,
|
||||
encoder: "advanced",
|
||||
tokenize: "forward",
|
||||
document: {
|
||||
index: [
|
||||
"docsSchemaDocument:type",
|
||||
"text",
|
||||
],
|
||||
store: true
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function finalize() {
|
||||
thisObject.docsIndex = undefined
|
||||
}
|
||||
|
||||
function setUpSearchEngine(callbackFunction) {
|
||||
|
||||
/*
|
||||
/*
|
||||
This is a way to avoid indexing the docs, if the user does not want to.
|
||||
*/
|
||||
let docsSpaceNode = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadByNodeType('Docs Space')
|
||||
@@ -63,97 +77,115 @@ function newFoundationsDocsSearchEngine() {
|
||||
/* Search in Nodes */
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsNodeSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Node' + project + i, // since we don't have a real ID we concatenate some values to achieve an unique ID
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsNodeSchema[i],
|
||||
category: 'Node',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsNodeSchema[i]),
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInConcepts() {
|
||||
/* Search in Concepts */
|
||||
//!* Search in Concepts *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsConceptSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Concept' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsConceptSchema[i],
|
||||
category: 'Concept',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsConceptSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInNTopics() {
|
||||
/* Search in Topics */
|
||||
//!* Search in Topics *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsTopicSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Topic' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsTopicSchema[i],
|
||||
category: 'Topic',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsTopicSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInTutorials() {
|
||||
/* Search in Tutorials */
|
||||
//!* Search in Tutorials *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsTutorialSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Tutorial' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsTutorialSchema[i],
|
||||
category: 'Tutorial',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsTutorialSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInReviews() {
|
||||
/* Search in Reviews */
|
||||
//!* Search in Reviews *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsReviewSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Review' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsReviewSchema[i],
|
||||
category: 'Review',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsReviewSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInBooks() {
|
||||
/* Search in Books */
|
||||
//!* Search in Books *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.docsBookSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Book' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.docsBookSchema[i],
|
||||
category: 'Book',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.docsBookSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
|
||||
function searchInWorkspaces() {
|
||||
/* Search in Workspace */
|
||||
//!* Search in Workspace *!/
|
||||
for (let i = 0; i < SCHEMAS_BY_PROJECT.get(project).array.workspaceSchema.length; i++) {
|
||||
documentIndex = {
|
||||
phraseCount: {}, // here we have an object with properties matching it paragraph style, and each property is a map of phrases and their total count.
|
||||
id: 'Workspace' + project + i,
|
||||
docsSchemaDocument: SCHEMAS_BY_PROJECT.get(project).array.workspaceSchema[i],
|
||||
category: 'Workspace',
|
||||
project: project
|
||||
project: project,
|
||||
// We are creating a single field containing the definition and paragraphs concatenated, leveraging the search logic to the algorithm
|
||||
text: extractTextContentFromSchemaDocs(SCHEMAS_BY_PROJECT.get(project).array.workspaceSchema[i])
|
||||
}
|
||||
indexDocument(documentIndex)
|
||||
thisObject.docsIndex.push(documentIndex)
|
||||
thisObject.documentIndex.add(documentIndex)
|
||||
|
||||
}
|
||||
asyncCallFinished()
|
||||
}
|
||||
@@ -161,121 +193,84 @@ function newFoundationsDocsSearchEngine() {
|
||||
function asyncCallFinished() {
|
||||
totalAsyncCallsFinished++
|
||||
if (totalAsyncCallsMade === totalAsyncCallsFinished) {
|
||||
|
||||
callbackFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function indexDocument(documentIndex) {
|
||||
|
||||
if (documentIndex.docsSchemaDocument === undefined) {
|
||||
function extractTextContentFromSchemaDocs(docsSchemaDocument) {
|
||||
if (docsSchemaDocument === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
if (documentIndex.docsSchemaDocument.topic !== undefined) {
|
||||
let paragraph = {
|
||||
style: 'Topic',
|
||||
text: documentIndex.docsSchemaDocument.topic
|
||||
}
|
||||
indexParagraph(paragraph)
|
||||
let textField = ''
|
||||
|
||||
if (docsSchemaDocument.topic !== undefined) {
|
||||
let paragraph = {text: docsSchemaDocument.topic}
|
||||
appendToTextField(paragraph.text)
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.tutorial !== undefined) {
|
||||
let paragraph = {
|
||||
style: 'Tutorial',
|
||||
text: documentIndex.docsSchemaDocument.tutorial
|
||||
}
|
||||
indexParagraph(paragraph)
|
||||
if (docsSchemaDocument.tutorial !== undefined) {
|
||||
let paragraph = {text: docsSchemaDocument.tutorial}
|
||||
appendToTextField(paragraph.text)
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.review !== undefined) {
|
||||
let paragraph = {
|
||||
style: 'Review',
|
||||
text: documentIndex.docsSchemaDocument.review
|
||||
}
|
||||
indexParagraph(paragraph)
|
||||
if (docsSchemaDocument.review !== undefined) {
|
||||
let paragraph = {text: docsSchemaDocument.review}
|
||||
appendToTextField(paragraph.text)
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.type !== undefined) {
|
||||
let paragraph = {
|
||||
style: 'Type',
|
||||
text: documentIndex.docsSchemaDocument.type
|
||||
}
|
||||
indexParagraph(paragraph)
|
||||
if (docsSchemaDocument.type !== undefined) {
|
||||
let paragraph = {text: docsSchemaDocument.type}
|
||||
appendToTextField(paragraph.text)
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.definition !== undefined) {
|
||||
if (docsSchemaDocument.definition !== undefined) {
|
||||
let paragraph = {
|
||||
style: 'Definition',
|
||||
text: documentIndex.docsSchemaDocument.definition.text,
|
||||
translations: documentIndex.docsSchemaDocument.definition.translations
|
||||
text: docsSchemaDocument.definition.text,
|
||||
translations: docsSchemaDocument.definition.translations
|
||||
}
|
||||
indexParagraph(paragraph)
|
||||
appendToTextField(' ')
|
||||
appendToTextField(paragraph.text)
|
||||
indexAllTranslations(paragraph)
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.paragraphs !== undefined) {
|
||||
for (let k = 0; k < documentIndex.docsSchemaDocument.paragraphs.length; k++) {
|
||||
let paragraph = documentIndex.docsSchemaDocument.paragraphs[k]
|
||||
indexParagraph(paragraph)
|
||||
|
||||
if (docsSchemaDocument.paragraphs !== undefined) {
|
||||
for (let k = 0; k < docsSchemaDocument.paragraphs.length; k++) {
|
||||
let paragraph = docsSchemaDocument.paragraphs[k]
|
||||
|
||||
appendToTextField(' ')
|
||||
appendToTextField(paragraph.text)
|
||||
indexAllTranslations(paragraph)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function indexAllTranslations(paragraph) {
|
||||
if (paragraph.translations === undefined) { return }
|
||||
for (i = 0; i < paragraph.translations.length; i++) {
|
||||
let translation = paragraph.translations[i]
|
||||
translation.style = paragraph.style
|
||||
indexParagraph(translation)
|
||||
if (paragraph.translations === undefined) {
|
||||
return
|
||||
}
|
||||
for (let j = 0; j < paragraph.translations.length; j++) {
|
||||
let translation = paragraph.translations[j]
|
||||
appendToTextField(' ')
|
||||
appendToTextField(translation.text)
|
||||
}
|
||||
}
|
||||
|
||||
function indexParagraph(paragraph) {
|
||||
if (paragraph.text === undefined) {
|
||||
return
|
||||
}
|
||||
if (paragraph.style === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
let text = paragraph.text.toLowerCase()
|
||||
let style = paragraph.style.toLowerCase()
|
||||
let stylePhraseCount = documentIndex.phraseCount[style]
|
||||
|
||||
if (stylePhraseCount === undefined) {
|
||||
stylePhraseCount = new Map()
|
||||
documentIndex.phraseCount[style] = stylePhraseCount
|
||||
}
|
||||
|
||||
text = UI.projects.foundations.utilities.strings.replaceSpecialCharactersForSpaces(text)
|
||||
|
||||
let splittedText = text.split(' ')
|
||||
|
||||
for (n = 0; n < splittedText.length; n++) {
|
||||
let phrase = ''
|
||||
for (let m = 0; m < 10; m++) {
|
||||
let word = splittedText[n + m]
|
||||
if (word !== undefined) {
|
||||
if (m === 0) {
|
||||
phrase = phrase + word
|
||||
} else {
|
||||
phrase = phrase + ' ' + word
|
||||
}
|
||||
let key = UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(phrase)
|
||||
|
||||
let thisPhraseCount = stylePhraseCount.get(key)
|
||||
if (thisPhraseCount === undefined) { thisPhraseCount = 0 }
|
||||
thisPhraseCount++
|
||||
|
||||
stylePhraseCount.set(key, thisPhraseCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
function appendToTextField(textToAppend) {
|
||||
textField += textToAppend
|
||||
}
|
||||
|
||||
return textField
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function setUpWorkspaceSchemas() {
|
||||
/*
|
||||
We will scan the whole workspace and create an array with all of its nodes.
|
||||
*/
|
||||
let rootNodes = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode.rootNodes
|
||||
let workspaceNode = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
||||
let rootNodes = workspaceNode.rootNodes
|
||||
let allNodesFound = []
|
||||
for (let i = 0; i < rootNodes.length; i++) {
|
||||
let rootNode = rootNodes[i]
|
||||
@@ -284,6 +279,7 @@ function newFoundationsDocsSearchEngine() {
|
||||
allNodesFound = allNodesFound.concat(nodeArray)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We will create a document for each node, so that can later be indexed into the search engine.
|
||||
*/
|
||||
@@ -296,45 +292,58 @@ function newFoundationsDocsSearchEngine() {
|
||||
let node = allNodesFound[i]
|
||||
|
||||
if (node.project === project) {
|
||||
let nodeNameTypePath = UI.projects.visualScripting.utilities.hierarchy.getNodeNameTypePath(node)
|
||||
|
||||
let docsSchemaDocument = {
|
||||
nodeId: node.id,
|
||||
nodeNameTypePath: nodeNameTypePath,
|
||||
type: node.type,
|
||||
definition: { text: node.name },
|
||||
paragraphs: []
|
||||
}
|
||||
if (node.config !== undefined) {
|
||||
let paragraph
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "Config"
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
paragraph = {
|
||||
style: "Json",
|
||||
text: node.config
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
}
|
||||
if (node.code !== undefined) {
|
||||
let paragraph
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "Code"
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
paragraph = {
|
||||
style: "Javascript",
|
||||
text: node.code
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
}
|
||||
let docsSchemaDocument = createDocsSchemaDocument(node)
|
||||
SCHEMAS_BY_PROJECT.get(project).array.workspaceSchema.push(docsSchemaDocument)
|
||||
SCHEMAS_BY_PROJECT.get(project).map.workspaceSchema.set(node.id, docsSchemaDocument)
|
||||
}
|
||||
|
||||
}
|
||||
//Ugly hack to insert also the workspace node itself into the list to be indexed later on
|
||||
if (project === 'Foundations') {
|
||||
let docsSchemaDocument = createDocsSchemaDocument(workspaceNode)
|
||||
SCHEMAS_BY_PROJECT.get(project).array.workspaceSchema.push(docsSchemaDocument)
|
||||
SCHEMAS_BY_PROJECT.get(project).map.workspaceSchema.set(workspaceNode.id, docsSchemaDocument)
|
||||
}
|
||||
}
|
||||
|
||||
function createDocsSchemaDocument(node) {
|
||||
let nodeNameTypePath = UI.projects.visualScripting.utilities.hierarchy.getNodeNameTypePath(node)
|
||||
|
||||
let docsSchemaDocument = {
|
||||
nodeId: node.id,
|
||||
nodeNameTypePath: nodeNameTypePath,
|
||||
type: node.type,
|
||||
definition: {text: node.name},
|
||||
paragraphs: []
|
||||
}
|
||||
if (node.config !== undefined) {
|
||||
let paragraph
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "Config"
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
paragraph = {
|
||||
style: "Json",
|
||||
text: node.config
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
}
|
||||
if (node.code !== undefined) {
|
||||
let paragraph
|
||||
paragraph = {
|
||||
style: "Title",
|
||||
text: "Code"
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
paragraph = {
|
||||
style: "Javascript",
|
||||
text: node.code
|
||||
}
|
||||
docsSchemaDocument.paragraphs.push(paragraph)
|
||||
}
|
||||
|
||||
return docsSchemaDocument
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,194 +17,37 @@ function newFoundationsDocsSearchResultsPage() {
|
||||
|
||||
function render() {
|
||||
|
||||
let resultsArary = []
|
||||
let docIndex = UI.projects.education.spaces.docsSpace.searchEngine.documentIndex
|
||||
let resultsArray = []
|
||||
let initialTime = new Date()
|
||||
buildResultsArray()
|
||||
buildHTML()
|
||||
|
||||
function buildResultsArray() {
|
||||
for (let i = 0; i < UI.projects.education.spaces.docsSpace.searchEngine.docsIndex.length; i++) {
|
||||
let documentIndex = UI.projects.education.spaces.docsSpace.searchEngine.docsIndex[i]
|
||||
let documentPoints = 0
|
||||
|
||||
for (const style in documentIndex.phraseCount) {
|
||||
let key = UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(UI.projects.education.spaces.docsSpace.commandInterface.command.toLowerCase())
|
||||
let thisPhraseCount = documentIndex.phraseCount[style].get(key)
|
||||
if (thisPhraseCount === undefined) {
|
||||
thisPhraseCount = 0
|
||||
}
|
||||
let searchByType = docIndex.search(UI.projects.education.spaces.docsSpace.commandInterface.command.toLowerCase(), {
|
||||
pluck: 'docsSchemaDocument:type',
|
||||
enrich: true,
|
||||
limit: 10000
|
||||
})
|
||||
let searchByText = docIndex.search(UI.projects.education.spaces.docsSpace.commandInterface.command.toLowerCase(), {
|
||||
pluck: 'text',
|
||||
enrich: true,
|
||||
limit: 10000
|
||||
})
|
||||
|
||||
if (documentIndex.docsSchemaDocument.type !== undefined) {
|
||||
if (key === UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(documentIndex.docsSchemaDocument.type.toLowerCase())) {
|
||||
documentPoints = documentPoints + thisPhraseCount * 100
|
||||
}
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.topic !== undefined) {
|
||||
if (key === UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(documentIndex.docsSchemaDocument.topic.toLowerCase())) {
|
||||
documentPoints = documentPoints + thisPhraseCount * 200
|
||||
}
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.tutorial !== undefined) {
|
||||
if (key === UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(documentIndex.docsSchemaDocument.tutorial.toLowerCase())) {
|
||||
documentPoints = documentPoints + thisPhraseCount * 200
|
||||
}
|
||||
}
|
||||
if (documentIndex.docsSchemaDocument.review !== undefined) {
|
||||
if (key === UI.projects.foundations.utilities.strings.cleanTextOfCommonWordEndings(documentIndex.docsSchemaDocument.review.toLowerCase())) {
|
||||
documentPoints = documentPoints + thisPhraseCount * 200
|
||||
}
|
||||
}
|
||||
|
||||
switch (style) {
|
||||
case 'topic': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 100
|
||||
break
|
||||
}
|
||||
case 'tutorial': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 100
|
||||
break
|
||||
}
|
||||
case 'review': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 100
|
||||
break
|
||||
}
|
||||
case 'type': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 50
|
||||
break
|
||||
}
|
||||
case 'definition': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 9
|
||||
break
|
||||
}
|
||||
case 'title': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 10
|
||||
break
|
||||
}
|
||||
case 'subtitle': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 8
|
||||
break
|
||||
}
|
||||
case 'text': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 2
|
||||
break
|
||||
}
|
||||
case 'list': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 2
|
||||
break
|
||||
}
|
||||
case 'note': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 4
|
||||
break
|
||||
}
|
||||
case 'warning': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 6
|
||||
break
|
||||
}
|
||||
case 'error': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 6
|
||||
break
|
||||
}
|
||||
case 'important': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 7
|
||||
break
|
||||
}
|
||||
case 'success': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 5
|
||||
break
|
||||
}
|
||||
case 'callout': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 5
|
||||
break
|
||||
}
|
||||
case 'summary': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 6
|
||||
break
|
||||
}
|
||||
case 'section': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 8
|
||||
break
|
||||
}
|
||||
case 'table': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 3
|
||||
break
|
||||
}
|
||||
case 'hierarchy': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 3
|
||||
break
|
||||
}
|
||||
case 'json': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 2
|
||||
break
|
||||
}
|
||||
case 'javascript': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 2
|
||||
break
|
||||
}
|
||||
case 'gif': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 1
|
||||
break
|
||||
}
|
||||
case 'png': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 1
|
||||
break
|
||||
}
|
||||
case 'anchor': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 0
|
||||
break
|
||||
}
|
||||
case 'block': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 0
|
||||
break
|
||||
}
|
||||
case 'include': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 0
|
||||
break
|
||||
}
|
||||
case 'placeholder': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 0
|
||||
break
|
||||
}
|
||||
case 'link': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 1
|
||||
break
|
||||
}
|
||||
case 'youtube': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 1
|
||||
break
|
||||
}
|
||||
case 'chapter': {
|
||||
documentPoints = documentPoints + thisPhraseCount * 8
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (documentPoints === 0) { continue } // No matches anywhere
|
||||
|
||||
let result = {
|
||||
documentIndex: documentIndex,
|
||||
documentPoints: documentPoints
|
||||
}
|
||||
let added = false
|
||||
|
||||
if (resultsArary.length === 0) {
|
||||
resultsArary.push(result)
|
||||
added = true
|
||||
} else {
|
||||
for (let j = 0; j < resultsArary.length; j++) {
|
||||
let thisResult = resultsArary[j]
|
||||
if (result.documentPoints > thisResult.documentPoints) {
|
||||
resultsArary.splice(j, 0, result)
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (added === false) {
|
||||
resultsArary.push(result)
|
||||
}
|
||||
// Search in all fields and remove duplicates
|
||||
Promise.all([searchByType, searchByText]).then(
|
||||
function (values) {
|
||||
let flags = {}
|
||||
values.forEach(arrResult => {
|
||||
arrResult.forEach(result => {
|
||||
if (!flags[result.id]) {
|
||||
flags[result.id] = true;
|
||||
resultsArray.push({documentIndex: result.doc});
|
||||
}
|
||||
})
|
||||
})
|
||||
buildHTML()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function buildHTML() {
|
||||
const tabs = ['All', 'Nodes', 'Concepts', 'Topics', 'Tutorials', 'Reviews', 'Books', 'Workspace']
|
||||
@@ -231,8 +74,8 @@ function newFoundationsDocsSearchResultsPage() {
|
||||
HTML = HTML + '<p> ' + tab.toUpperCase() + '_TOTAL_RESULTS results (' + tab.toUpperCase() + '_TOTAL_SECONDS seconds)</p>'
|
||||
|
||||
let resultCounter = 0
|
||||
for (let j = 0; j < resultsArary.length; j++) {
|
||||
let result = resultsArary[j]
|
||||
for (let j = 0; j < resultsArray.length; j++) {
|
||||
let result = resultsArray[j]
|
||||
|
||||
if (tab !== 'All') {
|
||||
if (tab.indexOf(result.documentIndex.category) < 0) {
|
||||
|
||||
@@ -319,7 +319,7 @@ function newEducationTutorialSpace() {
|
||||
htmlImage.height = "100"
|
||||
} else if (icon === undefined) {
|
||||
// Legacy Code to handle icons being fetched by literal path
|
||||
// Note: This if statment should be removed once all tutoials have been refactored
|
||||
// Note: This if statement should be removed once all tutorials have been refactored
|
||||
let webParam = 'Icons/' + newImageProject + '/' + newImageName + '.png'
|
||||
htmlImage.src = webParam
|
||||
htmlImage.width = "100"
|
||||
@@ -378,7 +378,7 @@ function newEducationTutorialSpace() {
|
||||
config.controlDocs.page.type !== ''
|
||||
) {
|
||||
/*
|
||||
This produces the Docs to laod the specified page.
|
||||
This produces the Docs to load the specified page.
|
||||
*/
|
||||
UI.projects.education.spaces.docsSpace.openSpaceAreaAndNavigateTo(config.controlDocs.page.project, config.controlDocs.page.category, config.controlDocs.page.type, config.controlDocs.page.anchor)
|
||||
}
|
||||
@@ -391,7 +391,7 @@ function newEducationTutorialSpace() {
|
||||
workspacesCounter++
|
||||
if (config.workspaces === undefined) {
|
||||
/*
|
||||
The worspaces panel will remain as it is, and the user will be free to open or close it at will.
|
||||
The workspaces panel will remain as it is, and the user will be free to open or close it at will.
|
||||
*/
|
||||
return
|
||||
}
|
||||
@@ -853,7 +853,7 @@ function newEducationTutorialSpace() {
|
||||
}
|
||||
let previousNode
|
||||
/*
|
||||
Reseet the Status of Current and Previous Node
|
||||
Reset the Status of Current and Previous Node
|
||||
so that RESUME goes to the right node.
|
||||
*/
|
||||
UI.projects.foundations.utilities.tutorial.saveTutorial(currentNode.payload, tutorial)
|
||||
@@ -1084,7 +1084,7 @@ function newEducationTutorialSpace() {
|
||||
|
||||
function findTutorialNode(node) {
|
||||
/*
|
||||
We will consider the tutorialRootNode the head of the hirierchy
|
||||
We will consider the tutorialRootNode the head of the hierarchy
|
||||
*/
|
||||
tutorialRootNode = node
|
||||
|
||||
@@ -1309,7 +1309,7 @@ function newEducationTutorialSpace() {
|
||||
function syncConfigIconWithDocumentIcon() {
|
||||
/*
|
||||
We update here the image of the document with whatever we find at the config, since
|
||||
we need to mechanism to keep this syncronized.
|
||||
we need to mechanism to keep this synchronized.
|
||||
*/
|
||||
if (nodeConfig.icon === undefined) {
|
||||
nodeConfig.icon = {
|
||||
|
||||
@@ -48,6 +48,10 @@ function newEducationUtilitiesLanguages() {
|
||||
languageLabel = 'Dutch'
|
||||
break
|
||||
}
|
||||
case 'AR': {
|
||||
languageLabel = 'Arabic'
|
||||
break
|
||||
}
|
||||
}
|
||||
return languageLabel
|
||||
}
|
||||
|
||||
+6
-6
@@ -49,7 +49,7 @@
|
||||
|
||||
/* these are module specific variables: */
|
||||
|
||||
let percentageBandwidthArray = []; // Here we keep the percentageBandwidthArray to be ploted every time the Draw() function is called by the AAWebPlatform.
|
||||
let percentageBandwidthArray = []; // Here we keep the percentageBandwidthArray to be plotted every time the Draw() function is called by the AAWebPlatform.
|
||||
|
||||
let zoomChangedEventSubscriptionId
|
||||
let offsetChangedEventSubscriptionId
|
||||
@@ -63,7 +63,7 @@
|
||||
function finalize() {
|
||||
try {
|
||||
|
||||
/* Stop listening to the necesary events. */
|
||||
/* Stop listening to the necessary events. */
|
||||
|
||||
UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.stopListening(zoomChangedEventSubscriptionId);
|
||||
UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.stopListening(offsetChangedEventSubscriptionId);
|
||||
@@ -72,7 +72,7 @@
|
||||
marketFiles.eventHandler.stopListening(marketFilesUpdatedEventSubscriptionId);
|
||||
dailyFiles.eventHandler.stopListening(dailyFilesUpdatedEventSubscriptionId);
|
||||
|
||||
/* Destroyd References */
|
||||
/* Destroyed References */
|
||||
|
||||
marketFiles = undefined;
|
||||
dailyFiles = undefined;
|
||||
@@ -113,7 +113,7 @@
|
||||
marketFile = marketFiles.getFile(pTimeFrame);
|
||||
fileCursor = dailyFiles.getFileCursor(pTimeFrame);
|
||||
|
||||
/* Listen to the necesary events. */
|
||||
/* Listen to the necessary events. */
|
||||
|
||||
zoomChangedEventSubscriptionId = UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.listenToEvent("Zoom Changed", onViewportZoomChanged);
|
||||
offsetChangedEventSubscriptionId = UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.listenToEvent("Position Changed", onViewportPositionChanged);
|
||||
@@ -354,7 +354,7 @@
|
||||
currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
}
|
||||
|
||||
/* Lests check if all the visible screen is going to be covered by percentageBandwidthArray. */
|
||||
/* Lets check if all the visible screen is going to be covered by percentageBandwidthArray. */
|
||||
|
||||
let lowerEnd = leftDate.valueOf();
|
||||
let upperEnd = rightDate.valueOf();
|
||||
@@ -508,7 +508,7 @@
|
||||
|
||||
if (percentageBandwidthArray.length > 0) {
|
||||
|
||||
/* This next section is to get ready in order to be able to plot dinamically constrained to the viewport */
|
||||
/* This next section is to get ready in order to be able to plot dynamically constrained to the viewport */
|
||||
|
||||
let visibleHeight = UI.projects.foundations.spaces.chartingSpace.viewport.visibleArea.bottomRight.y - UI.projects.foundations.spaces.chartingSpace.viewport.visibleArea.topLeft.y;
|
||||
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ function newCandlesPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
y: Y_AXIS_BUY
|
||||
};
|
||||
|
||||
/* Extra bounderies due to constrained space */
|
||||
/* Extra boundaries due to constrained space */
|
||||
|
||||
const upperLimit = frameTitleHeight + frameBodyHeight * 0.15;
|
||||
const downLimit = frameTitleHeight + frameBodyHeight * 0.85;
|
||||
|
||||
+7
-7
@@ -46,7 +46,7 @@
|
||||
|
||||
/* these are module specific variables: */
|
||||
|
||||
let volumes = []; // Here we keep the volumes to be ploted every time the Draw() function is called by the AAWebPlatform.
|
||||
let volumes = []; // Here we keep the volumes to be plotted every time the Draw() function is called by the AAWebPlatform.
|
||||
|
||||
let onMouseOverEventSuscriptionId
|
||||
let zoomChangedEventSubscriptionId
|
||||
@@ -63,7 +63,7 @@
|
||||
function finalize() {
|
||||
try {
|
||||
|
||||
/* Stop listening to the necesary events. */
|
||||
/* Stop listening to the necessary events. */
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.stopListening(zoomChangedEventSubscriptionId);
|
||||
UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.stopListening(offsetChangedEventSubscriptionId);
|
||||
@@ -72,7 +72,7 @@
|
||||
marketFiles.eventHandler.stopListening(marketFilesUpdatedEventSubscriptionId);
|
||||
dailyFiles.eventHandler.stopListening(dailyFilesUpdatedEventSubscriptionId);
|
||||
|
||||
/* Destroyd References */
|
||||
/* Destroyed References */
|
||||
|
||||
marketFiles = undefined;
|
||||
dailyFiles = undefined;
|
||||
@@ -116,7 +116,7 @@
|
||||
marketFile = marketFiles.getFile(pTimeFrame);
|
||||
fileCursor = dailyFiles.getFileCursor(pTimeFrame);
|
||||
|
||||
/* Listen to the necesary events. */
|
||||
/* Listen to the necessary events. */
|
||||
|
||||
zoomChangedEventSubscriptionId = UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.listenToEvent("Zoom Changed", onViewportZoomChanged);
|
||||
offsetChangedEventSubscriptionId = UI.projects.foundations.spaces.chartingSpace.viewport.eventHandler.listenToEvent("Position Changed", onViewportPositionChanged);
|
||||
@@ -352,7 +352,7 @@
|
||||
currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
}
|
||||
|
||||
/* Lests check if all the visible screen is going to be covered by volumes. */
|
||||
/* Lets check if all the visible screen is going to be covered by volumes. */
|
||||
|
||||
let lowerEnd = leftDate.valueOf();
|
||||
let upperEnd = rightDate.valueOf();
|
||||
@@ -650,7 +650,7 @@
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', 0.40)';
|
||||
|
||||
if (userPositionDate >= volume.begin && userPositionDate <= volume.end) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 0.40)'; // Current bar accroding to time
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 0.40)'; // Current bar according to time
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +674,7 @@
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', 0.40)';
|
||||
|
||||
if (userPositionDate >= volume.begin && userPositionDate <= volume.end) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 0.40)'; // Current volume accroding to time
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 0.40)'; // Current volume according to time
|
||||
}
|
||||
|
||||
browserCanvasContext.fill();
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="96 11 512 512"
|
||||
style="enable-background:new 96 11 512 512;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="create-reference.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||
inkscape:export-filename="E:\Superalgos\Projects\Foundations\Icons-SVG-Sources\menu\create-reference.png"
|
||||
inkscape:export-xdpi="100"
|
||||
inkscape:export-ydpi="100"><metadata
|
||||
id="metadata53"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs51" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview49"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.42382813"
|
||||
inkscape:cx="-330.802"
|
||||
inkscape:cy="797.57683"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g968-1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:#FD6A33;}
|
||||
.st1{fill:none;stroke:#4ACFD9;stroke-width:35;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:#9BAAAB;}
|
||||
.st3{fill:#4ACFD9;}
|
||||
.st4{fill:#0295AA;}
|
||||
.st5{fill:#FF8C29;}
|
||||
.st6{fill:#365558;}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<path
|
||||
class="st1"
|
||||
d="m 660.14266,606.29562 c -10,-50.1 -21.3,-115.2 -65.1,-149 -43.8,-33.8 -90.4,-37.6 -117.9,-77.6"
|
||||
id="path16" />
|
||||
<circle
|
||||
class="st2"
|
||||
cx="488.82132"
|
||||
cy="397.94778"
|
||||
r="37.799999"
|
||||
id="circle18" />
|
||||
|
||||
<path
|
||||
class="st0"
|
||||
d="m 390.62133,264.74781 -52.2,-52.1 c -2.7,-2.7 -2.7,-7.2 0,-9.9 l 2.5,-2.5 c 2.7,-2.7 7.2,-2.7 9.9,0 l 52.1,52.1 c 2.7,2.7 2.7,7.2 0,9.9 l -2.5,2.5 c -2.7,2.7 -7.1,2.7 -9.8,0 z"
|
||||
id="path26" />
|
||||
<path
|
||||
class="st5"
|
||||
d="m 355.92133,279.44781 -52.1,-52.1 c -2.7,-2.7 -2.7,-7.2 0,-9.9 l 2.5,-2.5 c 2.7,-2.7 7.2,-2.7 9.9,0 l 52.1,52.1 c 2.7,2.7 2.7,7.2 0,9.9 l -2.5,2.5 c -2.8,2.7 -7.2,2.7 -9.9,0 z"
|
||||
id="path28" />
|
||||
<path
|
||||
class="st0"
|
||||
d="m 348.62133,304.24781 -49.7,-49.6 c -3.4,-3.4 -9,-3.4 -12.4,0 v 0 c -3.4,3.4 -3.4,9 0,12.4 l 49.6,49.6 c 3.4,3.4 9,3.4 12.4,0 v 0 c 3.5,-3.5 3.5,-9 0.1,-12.4 z"
|
||||
id="path30" />
|
||||
<path
|
||||
class="st3"
|
||||
d="m 534.12133,351.14781 c 12.2,-12.2 12.2,-32.1 0,-44.3 l -62,-62 c -12.2,-12.2 -32.1,-12.2 -44.3,0 l -47.8,47.8 106.3,106.3 z"
|
||||
id="path32" />
|
||||
<path
|
||||
class="st4"
|
||||
d="m 332.22133,384.74781 62,62 c 12.2,12.2 32.1,12.2 44.3,0 l 47.8,-47.8 -106.3,-106.3 -47.8,47.8 c -12.2,12.2 -12.2,32.1 0,44.3 z"
|
||||
id="path34" />
|
||||
<path
|
||||
class="st4"
|
||||
d="m 422.52133,271.44781 c 5.8,-5.8 5.8,-15.4 0,-21.3 l -8.9,-8.9 c -5.8,-5.8 -15.4,-5.8 -21.3,0 l -31.9,31.9 30.1,30.1 z"
|
||||
id="path36" />
|
||||
<path
|
||||
class="st6"
|
||||
d="m 328.62133,326.34781 8.9,8.9 c 5.8,5.8 15.4,5.8 21.3,0 l 31.9,-31.9 -30.1,-30.1 -31.9,31.9 c -5.9,5.8 -5.9,15.3 -0.1,21.2 z"
|
||||
id="path38" />
|
||||
|
||||
<path
|
||||
class="st1"
|
||||
d="m 50.821333,-83.352191 c 10,50.1 21.3,115.2 65.099997,149 43.8,33.8 90.4,37.600001 117.9,77.700001"
|
||||
id="path12" /><circle
|
||||
class="st2"
|
||||
cx="233.82133"
|
||||
cy="143.34781"
|
||||
r="37.799999"
|
||||
id="circle14" /><g
|
||||
id="g24"
|
||||
transform="translate(46.321333,41.647809)">
|
||||
<path
|
||||
class="st3"
|
||||
d="m 310.3,165.8 c 5.8,-5.8 15.4,-5.8 21.3,0 l 3.5,3.5 6.2,-6.2 c 12.2,-12.2 12.2,-32.1 0,-44.3 l -62,-62 C 267.1,44.6 247.2,44.6 235,56.8 l -48.7,48.7 92.1,92.1 z"
|
||||
id="path20" />
|
||||
<path
|
||||
class="st4"
|
||||
d="m 139.4,196.8 62,62 c 12.2,12.2 32.1,12.2 44.3,0 l 4.4,-4.4 -3.5,-3.5 c -5.8,-5.8 -5.8,-15.4 0,-21.3 l 31.9,-31.9 -92.1,-92.1 -46.9,46.9 c -12.3,12.2 -12.3,32.2 -0.1,44.3 z"
|
||||
id="path22" />
|
||||
</g><rect
|
||||
x="-484.92621"
|
||||
y="12.338773"
|
||||
class="st1"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect14"
|
||||
style="fill:#f0353d" /><rect
|
||||
x="-356.92621"
|
||||
y="12.338773"
|
||||
class="st2"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect16"
|
||||
style="fill:#fd6a33" /><rect
|
||||
x="-228.92621"
|
||||
y="12.338773"
|
||||
class="st3"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect18"
|
||||
style="fill:#ff8c29" /><rect
|
||||
x="-100.9262"
|
||||
y="12.338773"
|
||||
class="st4"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect20"
|
||||
style="fill:#ffd1a9" /><rect
|
||||
x="-484.92621"
|
||||
y="140.33878"
|
||||
class="st5"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect22"
|
||||
style="fill:#365558" /><rect
|
||||
x="-356.92621"
|
||||
y="140.33878"
|
||||
class="st6"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect24"
|
||||
style="fill:#0295aa" /><rect
|
||||
x="-228.92621"
|
||||
y="140.33878"
|
||||
class="st7"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect26"
|
||||
style="fill:#4acfd9" /><rect
|
||||
x="-484.92621"
|
||||
y="268.33878"
|
||||
class="st8"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect28"
|
||||
style="fill:#9baaab" /><rect
|
||||
x="-356.92621"
|
||||
y="268.33878"
|
||||
class="st9"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect30"
|
||||
style="fill:#cdd4d5" /><rect
|
||||
x="-228.92621"
|
||||
y="268.33878"
|
||||
class="st10"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect32"
|
||||
style="fill:#e6eaea" /><rect
|
||||
x="-100.9262"
|
||||
y="268.33878"
|
||||
class="st11"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect34"
|
||||
style="fill:#ffffff" /><rect
|
||||
x="-484.92621"
|
||||
y="396.33878"
|
||||
class="st12"
|
||||
width="128"
|
||||
height="128"
|
||||
id="rect36"
|
||||
style="fill:#bcd643" /><g
|
||||
id="g968-1"
|
||||
transform="rotate(-135,714.30035,166.0977)"><g
|
||||
id="g1082"
|
||||
transform="translate(407.00461,-154.54378)"><g
|
||||
id="g1043"
|
||||
transform="rotate(135,481.3645,166.52488)"><g
|
||||
id="g1049"
|
||||
transform="translate(-1.7695853,17.474654)"><path
|
||||
id="path26-5-5"
|
||||
style="fill:#365558;fill-opacity:1"
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="9.437788"
|
||||
inkscape:original="M 103 11 C 99.18163 11 96 14.18162 96 18 L 96.070312 91.751953 C 96.070312 95.570333 99.18163 98.681641 103 98.681641 L 106.53516 98.681641 C 110.35353 98.681641 113.53711 95.500021 113.53711 91.681641 L 113.53711 18 C 113.53711 14.18162 110.35353 11 106.53516 11 L 103 11 z "
|
||||
d="M 103,1.5625 C 93.938999,1.5625 86.5625,8.9389867 86.5625,18 a 9.4387318,9.4387318 0 0 0 0,0.0098 l 0.07031,73.751953 C 86.638291,100.70245 94.058161,108.11914 103,108.11914 h 3.53516 c 9.061,0 16.43945,-7.37327 16.43945,-16.437499 V 18 c 0,-9.0642265 -7.37845,-16.4375 -16.43945,-16.4375 z"
|
||||
transform="translate(363.35484,24.774194)" /><path
|
||||
class="st0"
|
||||
d="m 459.42554,116.52578 -0.0707,-73.751226 c 0,-3.81838 3.18198,-7.00036 7.00035,-7.00036 h 3.53554 c 3.81837,0 7.00035,3.18198 7.00035,7.00036 v 73.680516 c 0,3.81838 -3.18198,7.00036 -7.00035,7.00036 h -3.53554 c -3.81837,0 -6.92964,-3.11127 -6.92964,-6.92965 z"
|
||||
id="path26-5"
|
||||
style="fill:#bcd643;fill-opacity:1" /></g></g><g
|
||||
id="g968-3"
|
||||
transform="rotate(180,491.97327,156.41818)"><path
|
||||
id="path26-5-5-5-5"
|
||||
style="fill:#365558;fill-opacity:1"
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="9.437788"
|
||||
inkscape:original="M 103 11 C 99.18163 11 96 14.18162 96 18 L 96.070312 91.751953 C 96.070312 95.570333 99.18163 98.681641 103 98.681641 L 106.53516 98.681641 C 110.35353 98.681641 113.53711 95.500021 113.53711 91.681641 L 113.53711 18 C 113.53711 14.18162 110.35353 11 106.53516 11 L 103 11 z "
|
||||
d="M 103,1.5625 C 93.938999,1.5625 86.5625,8.9389867 86.5625,18 a 9.4387318,9.4387318 0 0 0 0,0.0098 l 0.07031,73.751953 C 86.638291,100.70245 94.058161,108.11914 103,108.11914 h 3.53516 c 9.061,0 16.43945,-7.37327 16.43945,-16.437499 V 18 c 0,-9.0642265 -7.37845,-16.4375 -16.43945,-16.4375 z"
|
||||
transform="rotate(45,258.34465,606.85962)" /><path
|
||||
class="st0"
|
||||
d="m 507.83601,127.87824 52.10001,-52.199996 c 2.7,-2.700002 7.2,-2.700006 9.9,-1e-5 l 2.5,2.500004 c 2.7,2.699995 2.69999,7.199998 -10e-6,9.9 l -52.09999,52.099992 c -2.7,2.7 -7.2,2.7 -9.9,0 l -2.5,-2.5 c -2.7,-2.7 -2.70001,-7.09999 0,-9.79999 z"
|
||||
id="path26-5-7-9"
|
||||
style="fill:#bcd643;fill-opacity:1" /></g><g
|
||||
id="g968-9"
|
||||
transform="rotate(-90,492.63263,156.46704)"><path
|
||||
id="path26-5-5-5-8"
|
||||
style="fill:#365558;fill-opacity:1"
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="9.437788"
|
||||
inkscape:original="M 103 11 C 99.18163 11 96 14.18162 96 18 L 96.070312 91.751953 C 96.070312 95.570333 99.18163 98.681641 103 98.681641 L 106.53516 98.681641 C 110.35353 98.681641 113.53711 95.500021 113.53711 91.681641 L 113.53711 18 C 113.53711 14.18162 110.35353 11 106.53516 11 L 103 11 z "
|
||||
d="M 103,1.5625 C 93.938999,1.5625 86.5625,8.9389867 86.5625,18 a 9.4387318,9.4387318 0 0 0 0,0.0098 l 0.07031,73.751953 C 86.638291,100.70245 94.058161,108.11914 103,108.11914 h 3.53516 c 9.061,0 16.43945,-7.37327 16.43945,-16.437499 V 18 c 0,-9.0642265 -7.37845,-16.4375 -16.43945,-16.4375 z"
|
||||
transform="rotate(45,258.34465,606.85962)" /><path
|
||||
class="st0"
|
||||
d="m 507.83601,127.87824 52.10001,-52.199996 c 2.7,-2.700002 7.2,-2.700006 9.9,-1e-5 l 2.5,2.500004 c 2.7,2.699995 2.69999,7.199998 -10e-6,9.9 l -52.09999,52.099992 c -2.7,2.7 -7.2,2.7 -9.9,0 l -2.5,-2.5 c -2.7,-2.7 -2.70001,-7.09999 0,-9.79999 z"
|
||||
id="path26-5-7-34"
|
||||
style="fill:#bcd643;fill-opacity:1" /></g><path
|
||||
id="path26-5-5-5-07"
|
||||
style="fill:#365558;fill-opacity:1"
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="9.437788"
|
||||
inkscape:original="M 103 11 C 99.18163 11 96 14.18162 96 18 L 96.070312 91.751953 C 96.070312 95.570333 99.18163 98.681641 103 98.681641 L 106.53516 98.681641 C 110.35353 98.681641 113.53711 95.500021 113.53711 91.681641 L 113.53711 18 C 113.53711 14.18162 110.35353 11 106.53516 11 L 103 11 z "
|
||||
d="M 103,1.5625 C 93.938999,1.5625 86.5625,8.9389867 86.5625,18 a 9.4387318,9.4387318 0 0 0 0,0.0098 l 0.07031,73.751953 C 86.638291,100.70245 94.058161,108.11914 103,108.11914 h 3.53516 c 9.061,0 16.43945,-7.37327 16.43945,-16.437499 V 18 c 0,-9.0642265 -7.37845,-16.4375 -16.43945,-16.4375 z"
|
||||
transform="rotate(45,258.34465,606.85962)" /><path
|
||||
class="st0"
|
||||
d="m 507.83601,127.87824 52.10001,-52.199996 c 2.7,-2.700002 7.2,-2.700006 9.9,-1e-5 l 2.5,2.500004 c 2.7,2.699995 2.69999,7.199998 -10e-6,9.9 l -52.09999,52.099992 c -2.7,2.7 -7.2,2.7 -9.9,0 l -2.5,-2.5 c -2.7,-2.7 -2.70001,-7.09999 0,-9.79999 z"
|
||||
id="path26-5-7-7"
|
||||
style="fill:#bcd643;fill-opacity:1" /></g></g></svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
File diff suppressed because it is too large.
Load diff
@@ -34,7 +34,7 @@
|
||||
"config": true
|
||||
},
|
||||
"initialValues": {
|
||||
"config": "{ \n\"startDate\": \"2020-01-01\"\n}"
|
||||
"config": "{ \n\"startDate\": \"2021-01-01\"\n}"
|
||||
},
|
||||
"level": 3,
|
||||
"attachingRules": {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"label": "Send Test Message",
|
||||
"workingLabel": "Sending Message",
|
||||
"workDoneLabel": "Message Sent",
|
||||
"workFailedLabel": "Message not Delived",
|
||||
"workFailedLabel": "Message not Delivered",
|
||||
"iconPathOn": "run",
|
||||
"iconPathOff": "run",
|
||||
"actionFunction": "payload.executeAction"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"type": "Reviews",
|
||||
"definition": {
|
||||
"text": "This book is a cataloge of all types of reviews at the Docs.",
|
||||
"text": "This book is a catalogue of all types of reviews at the Docs.",
|
||||
"updated": 1621437863554
|
||||
},
|
||||
"paragraphs": [
|
||||
{
|
||||
"style": "Chapter",
|
||||
"text": "I->Foundations->Review->Superalgos Project Review->These are reviews of the project submited by users.",
|
||||
"text": "I->Foundations->Review->Superalgos Project Review->These are reviews of the project submitted by users.",
|
||||
"updated": 1621437834465
|
||||
}
|
||||
]
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Plugin Workspace",
|
||||
"definition": {
|
||||
"text": "Refers to a Workspace created by a user, contributed to the project as a plugin and distributed with the software package. Plugin workspaces are useful to give users access to ready-to-run strategies, demos, tutorials, or intoductions to areas of the system under development.",
|
||||
"text": "Refers to a Workspace created by a user, contributed to the project as a plugin and distributed with the software package. Plugin workspaces are useful to give users access to ready-to-run strategies, demos, tutorials, or introductions to areas of the system under development.",
|
||||
"updated": 1629895587555,
|
||||
"translations": [
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Project Schema File",
|
||||
"definition": {
|
||||
"text": "It is the most basic and low level system-wide configuration file. You will find it at the Projects folder. It contains a list of all integrated projects and for each one the list of javascript modules organized in different categories, like Function Libraries, Utilities, Spaces, Globals, etc; in turn organized into the broather categories UI, TS and PL.",
|
||||
"text": "It is the most basic and low level system-wide configuration file. You will find it at the Projects folder. It contains a list of all integrated projects and for each one the list of javascript modules organized in different categories, like Function Libraries, Utilities, Spaces, Globals, etc; in turn organized into the broader categories UI, TS and PL.",
|
||||
"updated": 1614939492529
|
||||
},
|
||||
"paragraphs": [
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Remove Distance to Parent Node",
|
||||
"definition": {
|
||||
"text": "The distance setting is dissabled and the node may assume any distance to its parent.",
|
||||
"text": "The distance setting is disabled and the node may assume any distance to its parent.",
|
||||
"updated": 1610030359012
|
||||
},
|
||||
"paragraphs": [
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "@BeginCurrentMinute: This will instruct the Bot to use a timestamp at the begining of the current minute."
|
||||
"text": "@BeginCurrentMinute: This will instruct the Bot to use a timestamp at the beginning of the current minute."
|
||||
},
|
||||
{
|
||||
"style": "Javascript",
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Set Node Arrangement to Concave",
|
||||
"definition": {
|
||||
"text": "The node adopts a slot on a circumsference around its parent node. In the icon’s graphic, the orange dot represents the parent node, and the blue dots represent the node adopting the specific arrangement style.",
|
||||
"text": "The node adopts a slot on a circumference around its parent node. In the icon’s graphic, the orange dot represents the parent node, and the blue dots represent the node adopting the specific arrangement style.",
|
||||
"updated": 1610032139983
|
||||
},
|
||||
"paragraphs": [
|
||||
|
||||
+5
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un forward testing session es un modo de trading mediante el cual la instancia del Trading Bot realiza transacciones en vivo con una fracción definida por el usuario del capital disponible.\n",
|
||||
"updated": 1624379829550
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Сессия форвардного тестирования - это торговый режим, в котором экземпляр торгового бота выполняет реальную торговлю с определенной пользователем долей доступного капитала.",
|
||||
"updated": 1636195888530
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+5
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "El nodo market data task agrupa tareas de minería de datos que operan en un mercado específico.",
|
||||
"updated": 1624379923791
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Узел Задачи рыночных данных группирует задачи интеллектуального анализа данных, работающие на определенном рынке.",
|
||||
"updated": 1636195923570
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+5
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un paper trading session es un modo de trading mediante el cual la instancia del Trading Bot lee una fuente de datos de mercado en vivo, aplica las reglas definidas en el Trading System asociado y genera una simulación de trading.",
|
||||
"updated": 1624379661697
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Административная торговая сессия - это режим торговли, при котором экземпляр торгового бота считывает поток рыночных данных в реальном времени, применяет правила, определенные в соответствующей торговой системе, и генерирует торговую симуляцию.",
|
||||
"updated": 1636195850621
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "El rate scale controla la escala del eje vertical, es decir, la escala del asset cotizado, ya sea de la máquina del tiempo o del gráfico de la línea de tiempo, dependiendo de dónde se encuentre el nodo.",
|
||||
"updated": 1624494681459
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Шкала ставок управляет масштабом вертикальной оси, т.е. масштабом действующего актива, либо машины времени, либо диаграммы временной шкалы, в зависимости от того, где расположен узел.",
|
||||
"updated": 1636206834295
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "The formulas nodes there are used to expand the record definition adding fields that are not actually going to be saved on disk, to minimize space used, and they are going to be calculated at runtime. This allows proceeses that consume this data to have ell the fields available at runtime even though some were not actually saved on disk."
|
||||
"text": "The formulas nodes there are used to expand the record definition adding fields that are not actually going to be saved on disk, to minimize space used, and they are going to be calculated at runtime. This allows processes that consume this data to have ell the fields available at runtime even though some were not actually saved on disk."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "A formula may act in slightly different ways depending on the isCaculated attribute in the record property configuration:"
|
||||
"text": "A formula may act in slightly different ways depending on the isCalculated attribute in the record property configuration:"
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "isCalculated determines if the field is stored in the dataset or if, instead, is calculated at a later stage. A value true* means that the record is not stored. In the case isCaculated is not defined in the configuration, it is assumed to be false.",
|
||||
"text": "isCalculated determines if the field is stored in the dataset or if, instead, is calculated at a later stage. A value true* means that the record is not stored. In the case isCalculated is not defined in the configuration, it is assumed to be false.",
|
||||
"updated": 1621972714008
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Serial numbers start at 1 and increment by 1 with each intance of the object that is opened."
|
||||
"text": "Serial numbers start at 1 and increment by 1 with each instance of the object that is opened."
|
||||
},
|
||||
{
|
||||
"style": "Block",
|
||||
|
||||
+11
-11
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Space Settings",
|
||||
"definition": {
|
||||
"text": "The space settings node features controls over the phisics, proportions, and positioning of icons representing node, and their menus."
|
||||
"text": "The space settings node features controls over the physics, proportions, and positioning of icons representing node, and their menus."
|
||||
},
|
||||
"paragraphs": [
|
||||
{
|
||||
@@ -53,7 +53,7 @@
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "animationSteps adjusts the amount of steps the animation takes to open a node menu upon hovering over it. A higher value leads to smoother transtion.",
|
||||
"text": "animationSteps adjusts the amount of steps the animation takes to open a node menu upon hovering over it. A higher value leads to smoother transition.",
|
||||
"updated": 1631588728860
|
||||
},
|
||||
{
|
||||
@@ -73,46 +73,46 @@
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "radiusPercentage is the reference radious of the circular matrix that governs the distribution of items in the circular menu. Larger numbers cause items to spread appart while smaller numbers makes items lie closer to each other.",
|
||||
"text": "radiusPercentage is the reference radius of the circular matrix that governs the distribution of items in the circular menu. Larger numbers cause items to spread apart while smaller numbers makes items lie closer to each other.",
|
||||
"updated": 1631554041849
|
||||
},
|
||||
{
|
||||
"style": "Subtitle",
|
||||
"text": "Shorcut Properties"
|
||||
"text": "Shortcut Properties"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Shorcuts are key stroke combinations that helps users execute certain actions very quickly. To execute a shorcut users need to simultaniously press CTRL + SHIFT + a pre-defined key.",
|
||||
"text": "Shortcuts are key stroke combinations that helps users execute certain actions very quickly. To execute a Shortcut users need to simultaneously press CTRL + SHIFT + a pre-defined key.",
|
||||
"updated": 1625419324367
|
||||
},
|
||||
{
|
||||
"style": "Success",
|
||||
"text": "Shorcuts default values can be seen below. You can modify those values by changing the Config Properties listed below.",
|
||||
"text": "Shortcuts default values can be seen below. You can modify those values by changing the Config Properties listed below.",
|
||||
"updated": 1625419754545
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "toggleMapMode defines which key will be used as a Shorcut for entering and leaving the Map Mode.",
|
||||
"text": "toggleMapMode defines which key will be used as a Shortcut for entering and leaving the Map Mode.",
|
||||
"updated": 1625419803171
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "toggleDrawRelationshipLines defines which key will be used as a Shorcut for turning on and off the drawing of Reference Lines.",
|
||||
"text": "toggleDrawRelationshipLines defines which key will be used as a Shortcut for turning on and off the drawing of Reference Lines.",
|
||||
"updated": 1625419810253
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "toggleDrawParentLines defines which key will be used as a Shorcut for turning on and off the drawing of Parent Lines.",
|
||||
"text": "toggleDrawParentLines defines which key will be used as a Shortcut for turning on and off the drawing of Parent Lines.",
|
||||
"updated": 1625419816654
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "saveWorkspace defines which key will be used as a Shorcut for saving the Workspace.",
|
||||
"text": "saveWorkspace defines which key will be used as a Shortcut for saving the Workspace.",
|
||||
"updated": 1625419822252
|
||||
},
|
||||
{
|
||||
"style": "List",
|
||||
"text": "adjustAspectRation defines which key will be used as a Shorcut for forcing a Time Machine to adjust it's aspect ratio according to the size of the screen a user currently have.",
|
||||
"text": "adjustAspectRation defines which key will be used as a Shortcut for forcing a Time Machine to adjust it's aspect ratio according to the size of the screen a user currently have.",
|
||||
"updated": 1625419830418
|
||||
}
|
||||
]
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Therefore, this section of the data structure features information spaning those periods only."
|
||||
"text": "Therefore, this section of the data structure features information spanning those periods only."
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Therefore, this section of the data structure features information spaning those periods only."
|
||||
"text": "Therefore, this section of the data structure features information spanning those periods only."
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "The trigger stage is active from the instant the trigger-on event is triggered until either the trigger-off event or the take position event gets triggered. Therefore, this section of the data structure features information spaning those periods only."
|
||||
"text": "The trigger stage is active from the instant the trigger-on event is triggered until either the trigger-off event or the take position event gets triggered. Therefore, this section of the data structure features information spanning those periods only."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "The super scripts hierarchy may be used by developers who wish to create their own scripts for automating the deployment or manitenance of all sorts of structures of nodes across any of the hierarchies in the design space."
|
||||
"text": "The super scripts hierarchy may be used by developers who wish to create their own scripts for automating the deployment or maintenance of all sorts of structures of nodes across any of the hierarchies in the design space."
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un task manageres un dispositivo que se utiliza para organizar y controlar cualquier cantidad de tareas que, a su vez, controlan las instancias de bot. Utiliza un administrador de tareas para iniciar o detener varias tareas al mismo tiempo.",
|
||||
"updated": 1624493800354
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Диспетчер задач - это устройство, используемое для организации и управления любым количеством задач, которые, в свою очередь, управляют экземплярами ботов. Вы используете диспетчер задач для запуска или остановки нескольких задач одновременно.\n",
|
||||
"updated": 1636193320098
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
"language": "ES",
|
||||
"text": "Un task es el dispositivo que se utiliza para controlar las instancias de bots, es decir, para iniciar y detener bots, incluidos sensores, indicadores y trading bots.",
|
||||
"updated": 1624454879222
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Задача - это устройство, используемое для управления экземплярами ботов, то есть для запуска и остановки ботов, включая датчики, индикаторы и торгового бота.\n",
|
||||
"updated": 1636193239036
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
"text": "Un time machine sincroniza múltiples gráficos de línea de tiempo en la misma línea de tiempo. Gráficos de línea de tiempo dentro de un time machine pueden tener diferentes escalas de tasas o escalas de marco de tiempo, pero su escala de tiempo siempre coincidirá. ",
|
||||
"updated": 1628644798838,
|
||||
"style": "Definition"
|
||||
},
|
||||
{
|
||||
"language": "RU",
|
||||
"text": "Машина времени синхронизирует несколько графиков временной шкалы на одной и той же временной шкале. Графики временной шкалы в машине времени могут иметь разные шкалы скорости или шкалы временных рамок, но их шкала времени всегда будет совпадать.",
|
||||
"updated": 1636199722951
|
||||
}
|
||||
],
|
||||
"updated": 1628644911381
|
||||
|
||||
Loaded 100 of 351 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user