Merge branch 'develop' of https://github.com/Superalgos/Superalgos into develop

This commit is contained in:
gitforkgit committed 2021-10-14 22:55:00 +02:00
commit c3c4b384e9
1129 files changed
+107549 -253747

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
name: Build/release
on:
push:
tags:
- '*'
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macos-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 14
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.github_token }}
# 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') }}
+3
View File
@@ -4,6 +4,8 @@ My-Workspaces
My-Social-Trading-Data
My-Network-Nodes-Data
My-Secrets
My-Data-Storage
My-Log-Files
debug.log
.DS_Store
*.db
@@ -17,3 +19,4 @@ node_modules
launch.json
package-lock.json
.idea
dist
+11 -5
View File
@@ -1,19 +1,25 @@
{
"files.exclude": {
"**/Data-Storage": true,
"**/Documentation": true,
"**/Log-Files": true,
"**/node_modules": true,
"**/Deprecated-Code": true,
"**/My-Social-Trading-Data": true,
"**/My-Network-Nodes-Data": true,
"**/My-Workspaces": true,
"**/My-Secrets": true,
"**/My-Data-Storage": true,
"**/My-Log-Files": true,
},
"search.exclude": {
"**/Data-Storage": true,
"**/Documentation": true,
"**/Log-Files": true,
"**/node_modules": true,
"**/Deprecated-Code": true,
"**/My-Social-Trading-Data": true
"**/My-Social-Trading-Data": true,
"**/My-Network-Nodes-Data": true,
"**/My-Workspaces": true,
"**/My-Secrets": true,
"**/My-Data-Storage": true,
"**/My-Log-Files": true,
},
"search.maintainFileSearchCache": true
}
+4
View File
@@ -0,0 +1,4 @@
brew "git"
brew "node"
brew "npm"
brew "python@3.9"
+1 -1
View File
@@ -12,5 +12,5 @@ RUN apk add --no-cache --virtual .build-deps make g++ \
USER superalgos
EXPOSE 34248
EXPOSE 18041
VOLUME ["/app/Data-Storage", "/app/Log-Files", "/app/My-Workspaces"]
VOLUME ["/app/Platform/My-Data-Storage", "/app/Platform/My-Log-Files", "/app/Platform/My-Workspaces"]
ENTRYPOINT ["node", "platform", "noBrowser"]
+273
View File
@@ -0,0 +1,273 @@
# Superalgos Docker Guide
## Table of Contents
- [Introduction](#introduction)
- [Installation](#installation)
- [Mac OS](#mac-os)
- [Windows](#windows)
- [Linux and BSD](#linux-and-bsd)
- [Running Superalgos](#running-superalgos)
- [Using Docker-Compose](#using-docker-compose)
- [Docker Best Practices](#docker-best-practices)
- [Docker Development Best Practices](#docker-development-best-practices)
- [Dockerfile Best Practices](#dockerfile-best-practices)
- [Twelve Factor App](#twelve-factor-app)
## 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.
[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.
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.
It is also worth noting that [Superalgos](https://github.com/Superalgos/Superalgos) is very resource intense so it is best to get acquainted with the software by running it on a fast computer with a good amount of RAM as opposed to a tiny, slow Raspberry Pi. But, once you are ready to run a production deployment, then a more economical server is preferred.
Docker container images are hosted on `ghcr`. You can browse the containers in the [Packages section of the code repository](https://github.com/users/Superalgos/packages/container/package/superalgos).
> **Note:** The container and the application are still under heavy development and testing. Please join the [Superalgos SysAdmins Group](https://t.me/superalgossysadmins) to discuss any issues you may run into.
## Installation
First, Docker Desktop needs to be installed on a Mac or Windows computer in order to run the containers. Linux and BSD users will need Docker Engine. Docker-compose is also recommended and it should be included with Docker Desktop, but it may need to be installed separately.
### Mac OS
Docker can be downloaded from the Docker Store following the [directions in the official Docker Docs](https://docs.docker.com/desktop/mac/install/). It can also be installed from the command line using Homebrew.
```shell
brew cask install docker
brew install docker-compose
```
Then, make sure Docker Desktop is running. An easy way to check is to push `Cmd + space` then type `docker.app` in the search bar. You should also see the little whale icon in the top menu bar near the clock.
### Windows
Windows requires a few more steps than Mac OS, but it can also be downloaded from the Docker Store following the [directions in the official Docker Docs](https://docs.docker.com/desktop/windows/install/). It can also be installed from the command line using Chocolatey.
```shell
choco install docker-desktop
```
Docker should automatically start after installation. If you don't see the whale icon in the tray by the clock, then find `Docker` in the start menu.
### 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.
```shell
# install the requirements
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# 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
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
# install docker engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose
```
Docker should automatically start when it is done installing. You can check its status with `systemctl status docker`. To make things easier, ensure your user is added to the `docker` group. Type `id` at the command prompt and you should see something like `groups=...999(docker)`. If you don't see it listed, you can add yourself with `sudo usermod -a -G docker <username>`.
## 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.
```shell
docker run --rm ghcr.io/superalgos/superalgos:latest
```
You'll see some messages showing the container being downloaded and then some messages from the application itself showing that it is starting up and ready to accept connections. We'll stop the container now and add in a few more options so make it more useful, so press `ctrl + c` to exit.
We'll need to expose some ports so we can actually connect to it from our browser. Also, we'll want to create a few directories on our host file system so we can save, or persist, data between container reboots.
- `-d` to run the container daemonized, in the background
- `-p` to map ports to the host system to allow connections
- `-v` to mount local directories inside the container to persist data
- `--name` to assign a name to the container for easier reference
```shell
# create the data directories
mkdir -p Data-Storage Log-Files My-Workspaces
# run the container with the extra options
docker run \
-d \
--rm \
--name superalgos \
--user $(id -u):$(id -g) \
-p 18041:18041 \
-p 34248:34248 \
-v $(pwd)/Data-Storage:/app/Data-Storage \
-v $(pwd)/Log-Files:/app/Log-Files \
-v $(pwd)/My-Workspaces:/app/My-Workspaces \
ghcr.io/superalgos/superalgos:latest
```
You can check the status of the container with `docker ps -a` and view the logs with `docker logs superalgos`.
Note that you will see one error in the log output informing you that `git` is not installed. This is intentional and is not required for the bot to function properly.
Now you can open your browser and load the application front end. Try loading `http://localhost:34248` if you are on the same computer that is running the container, otherwise use the host ip, for example `http://192.168.1.10:34248`.
If you want to stop the container, you can run `docker stop superalgos`. When you want to upgrade the container, use:
```shell
docker pull ghcr.io/superalgos/superalgos:latest
docker stop superalgos
docker run \
-d \
--rm \
--name superalgos \
--user $(id -u):$(id -g) \
-p 18041:18041 \
-p 34248:34248 \
-v $(pwd)/Data-Storage:/app/Data-Storage \
-v $(pwd)/Log-Files:/app/Log-Files \
-v $(pwd)/My-Workspaces:/app/My-Workspaces \
ghcr.io/superalgos/superalgos:latest
```
Let's stop the container for now (`docker stop superalgos`) and we'll run it again using `docker-compose`.
Continue reading the [Docker Command Line documentation](https://docs.docker.com/engine/reference/commandline/cli/) for more details.
### 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.
Let's download the sample and edit it. If you don't use `vim`, change that command for your preferred editor.
```shell
wget https://raw.githubusercontent.com/Superalgos/Superalgos/master/Docker/docker-compose.yml
vim docker-compose.yml
```
Now, let's change some of the settings:
```yaml
version: "3"
services:
superalgos:
image: ghcr.io/superalgos/superalgos:latest
command: ["minMemo"]
user: "$UID:$GID"
ports:
- '34248:34248'
- '18041:18041'
volumes:
- ./Data-Storage:/app/Data-Storage
- ./Log-Files:/app/Log-Files
- ./My-Workspaces:/app/My-Workspaces
restart: on-failure
```
You can see we have the same ports and volumes mapped. We also get a few extra settings like `command`, `environment`, and `restart`.
- `command` adds an extra setting to the main startup, so the application ends up running with the full command `node platform noBrowser minMemo`. The base of that command is defined as the `ENTRYPOINT` in the `Dockerfile` that builds the container.
- `user` defines the UID and GID the container should run as so that the data can be persisted with the correct permissions in the Data-Storage, Log-Files, and My-Workspaces directories that we created on the host. If you leave this out, the container will use the built in `superalgos` user which has `uid: 1001` and `gid: 1001`. Instead of using variables, you could also hard-code these UID and GID numbers into the configuration.
- `restart` tells Docker to restart the container if an error occurs.
Save the file and exit the editor. If you are using `vim`, hit escape and then type `:wq!` or press `shift + Z + Z` (two capital Z's).
Now, start the container with `docker-compose up`. This will start the container in the foreground and you'll connect to the log output. Hit `ctrl + c` to exit. Going forward, you'll want to add the `-d` option to start the container and keep it running in the background.
```shell
# some preliminary configuration to set up the persistent data directories
mkdir -p Data-Storage Log-Files My-Workspaces
export UID=$(id -u)
export GID=$(id -g)
# run the container in the background
docker-compose up -d
```
Now you have several `docker-compose` commands at your disposal to interact with the container:
- `docker-compose ps` to see details of the container
- `docker-compose logs` to see the logs
- `docker-compose down` to stop and remove the instance of the container
- `docker-compose pull` to pull the container, or a new version of the `latest` tag
Putting some of those concepts together, you can keep the running container up to date with this one-liner:
```shell
docker-compose pull && docker-compose down && docker-compose up -d
```
Explore the full [Docker Compose documentation](https://docs.docker.com/compose/) for more information.
## Docker Best Practices
As with any technology, there are lots of ways of doing things. A lot of them will give the same end result, but some may have fewer steps, or be more secure, or be more maintainable. That is where "best practices" come in. They aren't there to necessarily tell you what to do and what not to do, but they are there to help guide you in the right direction. A lot of times, they help you avoid making architectural mistakes that could come back and bite you further down the road.
One general best practice when running a production deployment is to avoid breaking changes by pinning to specific container tags. The `shasum hash` and the `release` tags are the best to use. These will generally ensure you are always running the same code and it will only upgrade when configured to do so. The other tags will change which code they are pointing to more frequently and without notice.
- `latest` : the absolute latest build
- `master` : the latest master branch build
- `develop` : the latest develop branch build
- `<shasum hash>` : a specific git commit hash
- `<release>` : corresponds with a Github Release (git tag), i.e. `beta-10`
## Docker Development Best Practices
Docker has many advantages which can aid in every step from development through production deployment. There are some useful tips located directly in the [Docker documentation](https://docs.docker.com/develop/dev-best-practices/). Concisely, they are to keep the build images small, a few tips on when and how to persist data, and to use CI/CD for testing and deployment. All of these tips are used in one way or another as a part of the [Superalgos](https://github.com/Superalgos/Superalgos) project.
- Use a minimal base image and multi-stage build. Superalgos is currently using an [alpine](https://www.alpinelinux.org/) base image but [distroless](https://github.com/GoogleContainerTools/distroless) is becoming more common and some times using a base image like [python-slim](https://hub.docker.com/_/python) is the bast that can be achieved.
- The images are quite large (around 2 GB in size), unfortunately, because the codebase itself is large. We've recently put in a lot of effort to make these images as small as possible.
- The images are built automatically using Github Actions when pull requests are merged.
- With the correct configuration, data, like data mine and trading bot information, is persisted to the host using volume mounts
### Dockerfile Best Practices
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.
- 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.
### Twelve Factor App
[Superalgos](https://github.com/Superalgos/Superalgos) is a web app but it was originally designed to be run on a local workstation or server on a trusted network. However, I don't think it would be prudent to talk about Docker best practices without mentioning the [Twelve Factor App](https://12factor.net/) manifesto. Over time, [Superalgos](https://github.com/Superalgos/Superalgos) itself may iterate and implement more and more of these principles as more people get involved and more people deploy production environments.
The Twelve Factors:
- Codebase: One codebase tracked in revision control, many deploys
- Superalgos utilizes one GitHub repository
- Dependencies: Explicitly declare and isolate dependencies
- Superalgos is a node.js app and uses npm to track and install dependencies
- Config: Store config in the environment
- Superalgos does not use environment variables the moment for configuration. Options are passed on the command line at run time. Other configuration is hard coded into the Workspaces.
- Backing services: Treat backing services as attached resources
- Superalgos connects to external services via API calls over HTTP (TCP)
- Build, release, run: Strictly separate build and run stages
- Superalgos is deployed by end users in their own local environments
- Processes: Execute the app as one or more stateless processes
- Superalgos is one application
- Port binding: Export services via port binding
- Superalgos exposes an HTTP frontend port and a Websockets backend port (TCP)
- Concurrency: Scale out via the process model
- Superalgos can be clustered but the front end and backend do not necessarily scale out independently from each other
- Disposability: Maximize robustness with fast startup and graceful shutdown
- Superalgos is not stateless in that the data files must be persisted to disk. Also, Superalgos cannot run behind a load balancer and have requests randomly distributed to different backend servers.
- Dev/prod parity: Keep development, staging, and production as similar as possible
- Superalgos doesn't have its own production environment but the container makes it easy to ensure development environments are the same as what a user will see when they deploy it for themselves in their own production environment.
- Logs: Treat logs as event streams
- Superalgos sends its own application logs to standard out. The trading mine logs are sent to flat files (persisted through volume mounts)
- Admin processes: Run admin/management tasks as one-off processes
- Superalgos does not have any admin or management tasks outside of what is used to create the container at build time.
+4 -6
View File
@@ -6,14 +6,12 @@ services:
dockerfile: ./Docker/Dockerfile
image: ghcr.io/superalgos/superalgos:latest
command: ["minMemo"]
user: "$UID:$GID"
ports:
- '34248:34248'
- '18041:18041'
volumes:
- ../Data-Storage:/app/Data-Storage
- ../Log-Files:/app/Log-Files
- ../My-Workspaces:/app/My-Workspaces
environment:
PUID: '1000'
PGID: '1000'
- ../Platform/My-Data-Storage:/app/Platform/My-Data-Storage
- ../Platform/My-Log-Files:/app/Platform/My-Log-Files
- ../Platform/My-Workspaces:/app/Platform/My-Workspaces
restart: on-failure
+23 -9
View File
@@ -1,18 +1,32 @@
const path = require("path")
if (process.env.PACKAGED_PATH) {
basePath = process.env.PACKAGED_PATH
} else {
basePath = __dirname
}
exports.newEnvironment = function () {
let thisObject = {
BASE_PATH: basePath,
WEB_SERVER_URL: 'localhost',
CLIENT_WEB_SOCKETS_INTERFACE_PORT: 18041,
CLIENT_HTTP_INTERFACE_PORT: 34248,
PATH_TO_DATA_STORAGE: './Data-Storage',
PATH_TO_PROJECTS: './Projects',
PATH_TO_LOG_FILES: './Log-Files',
PATH_TO_PROJECTS_REQUIRED: './Projects',
PATH_TO_PROJECT_SCHEMA: './Projects/ProjectsSchema.json',
PATH_TO_CLIENT: './Platform',
PATH_TO_DEFAULT_WORKSPACE: './Projects/Foundations/Plugins/Workspaces',
PATH_TO_MY_WORKSPACES: './My-Workspaces',
PATH_TO_FONTS: './Platform/WebServer/Fonts'
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'),
PATH_TO_PROJECTS_REQUIRED: path.join(basePath, './Projects'),
PATH_TO_PROJECT_SCHEMA: path.join(basePath, './Projects/ProjectsSchema.json'),
PATH_TO_CLIENT: path.join(basePath, './Platform'),
PATH_TO_DEFAULT_WORKSPACE: path.join(basePath, './Projects/Foundations/Plugins/Workspaces'),
PATH_TO_MY_WORKSPACES: path.join(basePath, './Platform/My-Workspaces'),
PATH_TO_FONTS: path.join(basePath, './Platform/WebServer/Fonts')
}
if (process.env.PORTABLE_EXECUTABLE_DIR) {
thisObject.PATH_TO_DATA_STORAGE = path.join(process.env.PORTABLE_USER_DOCUMENTS, '/Superalgos/Platform/My-Data-Storage')
thisObject.PATH_TO_LOG_FILES = path.join(process.env.PORTABLE_USER_DOCUMENTS, '/Superalgos/Platform/My-Log-Files')
thisObject.PATH_TO_MY_WORKSPACES = path.join(process.env.PORTABLE_USER_DOCUMENTS, '/Superalgos/Platform/My-Workspaces')
}
return thisObject
+3 -3
View File
@@ -8,15 +8,15 @@ exports.newEnvironment = function () {
DESKTOP_WEB_SOCKETS_INTERFACE_HOST: 'localhost',
CLIENT_HTTP_INTERFACE_PORT: 34248,
DESKTOP_HTTP_INTERFACE_PORT: 34249,
PATH_TO_DATA_STORAGE: './Data-Storage',
PATH_TO_DATA_STORAGE: './Platform/My-Data-Storage',
PATH_TO_LOG_FILES: './Platform/My-Log-Files',
PATH_TO_PROJECTS: './Projects',
PATH_TO_LOG_FILES: './Log-Files',
PATH_TO_PROJECTS_REQUIRED: './Projects',
PATH_TO_PROJECT_SCHEMA: './Projects/ProjectsSchema.json',
PATH_TO_CLIENT: './Platform',
PATH_TO_DESKTOP: './Desktop',
PATH_TO_DEFAULT_WORKSPACE: './Projects/Foundations/Plugins/Workspaces',
PATH_TO_MY_WORKSPACES: './My-Workspaces',
PATH_TO_MY_WORKSPACES: './Platform/My-Workspaces',
PATH_TO_FONTS: './Platform/WebServer/Fonts'
}
+7 -7
View File
@@ -79,7 +79,7 @@ exports.newGithubServer = function newGithubServer() {
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
userAgent: 'Superalgos Beta 12'
})
await getList()
@@ -207,7 +207,7 @@ exports.newGithubServer = function newGithubServer() {
const { Octokit } = SA.nodeModules.octokit
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
userAgent: 'Superalgos Beta 12'
})
await getPrList()
await mergePrs()
@@ -340,7 +340,7 @@ exports.newGithubServer = function newGithubServer() {
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (filesChanged.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.'
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (filesChanged.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged. \n\n If you intentionally submitted the extra files, the way to get your work merged is by first removing your User Profile file from the Plugins folder at your local installation and executing an app.contribute again. Then wait until the PR is merged (manually reviewed) and after that you put your User Profile file again and create a new PR only with that file with an app.contribute. That last PR should be merged automatically.'
});
await PL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
@@ -508,14 +508,14 @@ exports.newGithubServer = function newGithubServer() {
unless the existing one belongs to the same Github username.
*/
let userProfileIdMap = new Map()
let pluginFileNames = await SA.projects.foundations.utilities.plugins.getPluginFileNames(
let pluginFileNames = await SA.projects.communityPlugins.utilities.plugins.getPluginFileNames(
'Governance',
'User-Profiles'
)
for (let i = 0; i < pluginFileNames.length; i++) {
let pluginFileName = pluginFileNames[i]
let pluginFileContent = await SA.projects.foundations.utilities.plugins.getPluginFileContent(
let pluginFileContent = await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent(
'Governance',
'User-Profiles',
pluginFileName
@@ -558,13 +558,13 @@ exports.newGithubServer = function newGithubServer() {
unless the existing one belongs to the same Github username.
*/
let userProfileIdMap = new Map()
let pluginFileNames = await SA.projects.foundations.utilities.plugins.getPluginFileNames(
let pluginFileNames = await SA.projects.communityPlugins.utilities.plugins.getPluginFileNames(
'Governance',
'User-Profiles'
)
for (let i = 0; i < pluginFileNames.length; i++) {
let pluginFileName = pluginFileNames[i]
let pluginFileContent = await SA.projects.foundations.utilities.plugins.getPluginFileContent(
let pluginFileContent = await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent(
'Governance',
'User-Profiles',
pluginFileName
+207 -15
View File
@@ -631,7 +631,13 @@ exports.newHttpInterface = function newHttpInterface() {
break
case 'App':
{
// If running the electron app do not try to get git tool. I don't allow it.
if (process.env.SA_MODE === 'gitDisable') {
console.log('[WARNING] No contributions on binary distributions. Do manual installation')
break
}
switch (requestPath[2]) { // switch by command
case 'Contribute': {
try {
let commitMessage = unescape(requestPath[3])
@@ -641,7 +647,7 @@ exports.newHttpInterface = function newHttpInterface() {
const contributionsBranch = unescape(requestPath[7])
let error
/* Unsavping # */
/* Unsaving # */
for (let i = 0; i < 10; i++) {
commitMessage = commitMessage.replace('_SLASH_', '/')
commitMessage = commitMessage.replace('_HASHTAG_', '#')
@@ -649,7 +655,7 @@ exports.newHttpInterface = function newHttpInterface() {
contribute()
async function contribute() {
async function contribute() {
const { lookpath } = SA.nodeModules.lookpath
const gitpath = await lookpath('git')
if (gitpath === undefined) {
@@ -725,7 +731,7 @@ exports.newHttpInterface = function newHttpInterface() {
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
userAgent: 'Superalgos Beta 12'
})
const repo = 'Superalgos'
@@ -864,6 +870,9 @@ exports.newHttpInterface = function newHttpInterface() {
await doGit()
if (error === undefined) {
// Run node setup to prepare instance for branch change
await runNodeSetup()
// Return to UI that Branch is suggessfully changed
SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse)
} else {
let docs = {
@@ -889,6 +898,27 @@ exports.newHttpInterface = function newHttpInterface() {
const git = simpleGit(options)
try {
await git.checkout(currentBranch)
// Check to see it main repo has been set as upstream
let remotes = await git.getRemotes();
let isUpstreamSet
for(let remote in remotes) {
if (remotes[remote].name === 'upstream') {
isUpstreamSet = true
} else {
isUpstreamSet = false
}
}
// If upstream has not been set. Set it now
if (isUpstreamSet === false){
await git.addRemote('upstream', 'https://github.com/Superalgos/Superalgos');
}
// Pull branch from main repo
await git.pull('upstream', currentBranch);
// Reset branch to match main repo
let upstreamLocation = `upstream/${currentBranch}`
await git.reset('hard', [upstreamLocation])
} catch (err) {
console.log('[ERROR] Error changing current branch to ' + currentBranch)
console.log(err.stack)
@@ -896,6 +926,21 @@ exports.newHttpInterface = function newHttpInterface() {
}
}
async function runNodeSetup () {
console.log( "Running Node setup to adjust for new Branch" )
const process = SA.nodeModules.process
const childProcess = SA.nodeModules.childProcess
let dir = process.cwd()
let command = "node setup noShortcuts";
let stdout = childProcess.execSync( command,
{
cwd: dir
}).toString();
console.log("Node Setup has completed with the following result:", stdout)
}
} catch (err) {
console.log('[ERROR] httpInterface -> App -> Update -> Method call produced an error.')
console.log('[ERROR] httpInterface -> App -> Update -> err.stack = ' + err.stack)
@@ -971,6 +1016,148 @@ exports.newHttpInterface = function newHttpInterface() {
}
break
}
case 'FixAppSchema': {
/*
We will use this process when we have moved APP SCHEMA files from one project to another, and we need to fixt the
actions where this node was referenced, so that it points to the new project where the node has moved to.
*/
let customResponse = {
result: global.CUSTOM_OK_RESPONSE.result,
message: ''
}
SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(customResponse), httpResponse)
console.log('Fixing App Schemas...')
let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS)
let PROJECTS_MAP = new Map()
let directoryCount = 0
let allAppSchemas = []
let allAppSchemasFilePaths = []
let allAppSchemasFileProjects = []
for (let i = 0; i < projects.length; i++) {
let project = projects[i]
const fs = SA.nodeModules.fs
let folder = 'App-Schema'
let filePath = global.env.PATH_TO_PROJECTS + '/' + project + '/Schemas/'
SA.projects.foundations.utilities.filesAndDirectories.getAllFilesInDirectoryAndSubdirectories(filePath + folder, onFilesReady)
function onFilesReady(files) {
try {
let SCHEMA_MAP = new Map()
console.log('files.length... ' + files.length)
for (let k = 0; k < files.length; k++) {
let name = files[k]
let nameSplitted = name.split(folder)
let fileName = nameSplitted[1]
for (let i = 0; i < 10; i++) {
fileName = fileName.replace('\\', '/')
}
let fileToRead = filePath + folder + fileName
console.log('Reading file... ' + fileToRead)
let fileContent = fs.readFileSync(fileToRead)
let schemaDocument
try {
schemaDocument = JSON.parse(fileContent)
SCHEMA_MAP.set(schemaDocument.type, schemaDocument)
allAppSchemas.push(schemaDocument)
allAppSchemasFilePaths.push(fileToRead)
allAppSchemasFileProjects.push(project)
} catch (err) {
console.log('[ERROR] sendSchema -> Error Parsing JSON File: ' + fileToRead + ' .Error = ' + err.stack)
return
}
}
PROJECTS_MAP.set(project, SCHEMA_MAP)
directoryCount++
console.log('directoryCount = ' + directoryCount, 'projects.length = ' + projects.length)
//console.log(Array.from(PROJECTS_MAP.get(project).keys()))
if (directoryCount === projects.length) {
fixSchemas()
}
} catch (err) {
console.log(err.stack)
}
}
}
function fixSchemas() {
try {
console.log('fixSchemas...' + allAppSchemas.length)
let projects = SA.projects.foundations.utilities.filesAndDirectories.getDirectories(global.env.PATH_TO_PROJECTS)
const fs = SA.nodeModules.fs
let needFixing = 0
for (let i = 0; i < allAppSchemas.length; i++) {
let schemaDocument = allAppSchemas[i]
let wasUpdated = false
for (let j = 0; j < schemaDocument.menuItems.length; j++) {
let menuItem = schemaDocument.menuItems[j]
if (menuItem.relatedUiObject !== undefined && menuItem.relatedUiObjectProject === undefined) {
needFixing++
let hits = 0
let foundProject
let multiProject = ''
for (let k = 0; k < projects.length; k++) {
let project = projects[k]
let testDocument = PROJECTS_MAP.get(project).get(menuItem.relatedUiObject)
if (testDocument !== undefined) {
hits++
foundProject = project
multiProject = multiProject + ' -> ' + project
let fileProject = allAppSchemasFileProjects[i]
//console.log(fileProject, project)
if (fileProject === project) {
/* If the projec of the file is the same as the project found, then we consider this a match*/
hits = 1
continue
}
}
}
if (hits === 0) {
console.log('Problem With No Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject)
console.log('This Node Type was NOT FOUND at any project. ' + menuItem.relatedUiObject)
continue
}
if (hits === 1) {
console.log('Problem With One Solution #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found Project:' + foundProject)
menuItem.relatedUiObjectProject = foundProject
wasUpdated = true
continue
}
console.log('Problem With MULTIPLE Solutions #' + needFixing, ' Type: ' + schemaDocument.type, ' Action: ' + menuItem.action, ' Related UI Object: ' + menuItem.relatedUiObject, ' Found at these Projects:' + multiProject)
}
}
if (wasUpdated === true) {
let fileContent = JSON.stringify(schemaDocument, undefined, 4)
let filePath = allAppSchemasFilePaths[i]
//console.log('Saving File at ' + filePath)
//console.log(fileContent)
//fs.writeFileSync(filePath, fileContent)
}
}
} catch (err) {
console.log(err.stack)
}
}
break
}
}
function respondWithDocsObject(docs, error) {
@@ -1388,10 +1575,12 @@ exports.newHttpInterface = function newHttpInterface() {
let project = unescape(requestPath[2])
let folder = unescape(requestPath[3])
let response = await SA.projects.foundations.utilities.plugins.getPluginFileNames(
let response = await SA.projects.communityPlugins.utilities.plugins.getPluginFileNames(
project,
folder
)
).catch(err => {
console.log('[ERROR] httpInterface -> PluginFileNames -> err.stack = ' + err.stack)
})
SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(response), httpResponse)
@@ -1425,20 +1614,23 @@ exports.newHttpInterface = function newHttpInterface() {
fileName = 'Superalgos-PL.json'
}
let response = await SA.projects.foundations.utilities.plugins.getPluginFileContent(
await SA.projects.communityPlugins.utilities.plugins.getPluginFileContent(
project,
folder,
fileName
).catch(err => {
let error = {
result: 'Fail Because',
message: err
)
.then(response => {
SA.projects.foundations.utilities.httpResponses.respondWithContent(response, httpResponse)
}
SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse)
return
})
SA.projects.foundations.utilities.httpResponses.respondWithContent(response, httpResponse)
)
.catch(err => {
let error = {
result: 'Fail Because',
message: err
}
SA.projects.foundations.utilities.httpResponses.respondWithContent(JSON.stringify(error), httpResponse)
return
})
} catch (err) {
console.log('[ERROR] httpInterface -> LoadPlugin -> Method call produced an error.')
+1 -1
View File
@@ -63,7 +63,7 @@
//console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Name = ' + message.event.taskName)
//console.log('[INFO] Client -> Task Manager Server -> runTask -> Task Id = ' + message.event.taskId)
let path = './TaskServerRoot.js'
let path = global.env.BASE_PATH + '/TaskServerRoot.js'
/* Workarround to avoid having the same debug port at the forked process which makes it crash. */
for (let i = 0; i < process.execArgv.length; i++) {
+1 -1
View File
@@ -143,7 +143,7 @@ exports.newPlatformApp = function newPlatformApp() {
console.log('Http Interface .............................................. Listening at port ' + global.env.CLIENT_HTTP_INTERFACE_PORT)
console.log('')
console.log("You are running Superalgos Beta 11")
console.log("You are running Superalgos Beta 12")
console.log('')
console.log("What's new? These are the main new features in this version:")
console.log('')
+13
View File
@@ -485,6 +485,19 @@ function newCanvas() {
return
}
if (
event.shiftKey === true &&
(event.ctrlKey === true || event.metaKey === true) &&
(event.key === UI.projects.foundations.spaces.floatingSpace.settings.shortcuts.rescueFloatingObjectToMouse || event.key === UI.projects.foundations.spaces.floatingSpace.settings.shortcuts.rescueFloatingObjectToMouse.toLowerCase())
) {
UI.projects.foundations.spaces.floatingSpace.rescueFloatingObjectToMouse(thisObject.mouse.position)
if (event.preventDefault !== undefined) {
event.preventDefault()
}
return
}
let nodeOnFocus = await UI.projects.foundations.spaces.designSpace.workspace.getNodeThatIsOnFocus()
if (nodeOnFocus !== undefined) {
if (nodeOnFocus.payload.uiObject.codeEditor !== undefined) {
+35 -13
View File
@@ -1,4 +1,4 @@
function getSchemaDocument (node, project) {
function getSchemaDocument(node, project) {
if (node === null || node === undefined) {
console.log('[ERROR] Can not get the schema document of a null or undefined node ')
return
@@ -7,13 +7,35 @@ function getSchemaDocument (node, project) {
let APP_SCHEMA = SCHEMAS_BY_PROJECT.get(project)
if (APP_SCHEMA !== undefined) {
return SCHEMAS_BY_PROJECT.get(project).map.appSchema.get(node.type)
let schemaDocument = SCHEMAS_BY_PROJECT.get(project).map.appSchema.get(node.type)
/*
As of today, we are still splitting the codebase into multiple projects and there are Menu Actions which do not
have a well defined relatedUIObjectProject. There are a few techniques in place to try to guess it, but
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
between nodes belonging to more than one project.
*/
if (schemaDocument === undefined) {
for (let j = 0; j < PROJECTS_SCHEMA.length; j++) {
let project = PROJECTS_SCHEMA[j].name
schemaDocument = SCHEMAS_BY_PROJECT.get(project).map.appSchema.get(node.type)
if (schemaDocument !== undefined) {
break
}
}
}
return schemaDocument
} else {
console.log('[ERROR] Could not get APP Scchema for project ' + node.project)
console.log('[ERROR] Could not get APP Schema for project ' + node.project)
}
}
function dynamicDecimals (value, minDecimals) {
function dynamicDecimals(value, minDecimals) {
if (minDecimals === undefined) {
minDecimals = 0
}
@@ -26,7 +48,7 @@ function dynamicDecimals (value, minDecimals) {
return returnValue
}
function convertTimeFrameToName (pTimeFrame) {
function convertTimeFrameToName(pTimeFrame) {
for (let i = 0; i < dailyTimeFramesArray.length; i++) {
let period = dailyTimeFramesArray[i]
if (period[0] === pTimeFrame) {
@@ -42,7 +64,7 @@ function convertTimeFrameToName (pTimeFrame) {
}
}
function nextPorwerOf10 (number) {
function nextPorwerOf10(number) {
for (let i = -10; i <= 10; i++) {
if (number < Math.pow(10, i)) {
return Math.pow(10, i)
@@ -50,18 +72,18 @@ function nextPorwerOf10 (number) {
}
}
function pad (str, max) {
function pad(str, max) {
str = str.toString()
return str.length < max ? pad('0' + str, max) : str
}
function moveToUserPosition (container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition, fitFunction) {
function moveToUserPosition(container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition, fitFunction) {
let targetPoint = {
x: currentDate.valueOf(),
y: currentRate
}
/* Put this point in the coordinate system of the UI.projects.foundations.spaces.chartingSpace.viewport */
/* Put this point in the coordinate system of the UI.projects.foundations.spaces.chartingSpace.viewport */
targetPoint = coordinateSystem.transformThisPoint(targetPoint)
targetPoint = UI.projects.foundations.utilities.coordinateTransformations.transformThisPoint(targetPoint, container)
@@ -81,7 +103,7 @@ function moveToUserPosition (container, currentDate, currentRate, coordinateSyst
container.displace(displaceVector)
}
function removeTime (datetime) {
function removeTime(datetime) {
if (datetime === undefined) { return }
let dateOnly = new Date(Math.trunc(datetime.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS)
@@ -89,14 +111,14 @@ function removeTime (datetime) {
return dateOnly
}
function newUniqueId () {
function newUniqueId() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
function splitTextIntoPhrases (text, wordsPerLine) {
function splitTextIntoPhrases(text, wordsPerLine) {
try {
if (text.split === undefined) {
return []
@@ -128,7 +150,7 @@ function splitTextIntoPhrases (text, wordsPerLine) {
}
}
function getTextWidth (text) {
function getTextWidth(text) {
var metrics = browserCanvasContext.measureText(text)
return metrics.width
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+3 -1
View File
@@ -48,7 +48,9 @@ SA.nodeModules = {
ccxt: require('ccxt'),
octokit: require("@octokit/rest"),
simpleGit: require('simple-git'),
lookpath: require('lookpath')
lookpath: require('lookpath'),
process: require('process'),
childProcess: require('child_process')
}
run()
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,63 @@
{
"type": "Algorithmic-Trading Project",
"menuItems": [
{
"action": "Add Missing Children",
"label": "Add Missing Children",
"iconPathOn": "algorithmic-trading-project",
"iconPathOff": "algorithmic-trading-project",
"iconProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Add UI Object",
"label": "Add Trading Mine",
"relatedUiObject": "Trading Mine",
"relatedUiObjectProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Add UI Object",
"label": "Add Trading Engine",
"relatedUiObject": "Trading Engine",
"relatedUiObjectProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Add UI Object",
"label": "Add Trading System",
"relatedUiObject": "Trading System",
"relatedUiObjectProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"actionFunction": "payload.executeAction",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity"
}
],
"isProjectHead": true,
"isTitleAllwaysVisible": false,
"addLeftIcons": true,
"isPinned": true,
"positionLocked": true,
"icon": "algorithmic-trading-project",
"childrenNodesProperties": [
{
"name": "projectDefinition",
"type": "node",
"childType": "Project Definition",
"project": "Foundations",
"autoAdd": true
}
]
}
@@ -7,28 +7,36 @@
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"dontShowAtFullscreen": true,
"actionFunction": "uiObject.configEditor.activate"
"actionFunction": "uiObject.configEditor.activate",
"actionProject": "Foundations"
},
{
"action": "Add UI Object",
"label": "Add Process Definition",
"relatedUiObject": "Process Definition",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Add UI Object",
"label": "Add Product Definition",
"relatedUiObject": "Product Definition",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Add UI Object",
"label": "Add Product Definition Folder",
"relatedUiObject": "Product Definition Folder",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -54,19 +62,22 @@
"name": "processes",
"type": "array",
"childType": "Process Definition",
"autoAdd": true
"autoAdd": true,
"project": "Foundations"
},
{
"name": "products",
"type": "array",
"childType": "Product Definition",
"autoAdd": true
"autoAdd": true,
"project": "Foundations"
},
{
"name": "productDefinitionFolders",
"type": "array",
"childType": "Product Definition Folder",
"autoAdd": true
"autoAdd": true,
"project": "Foundations"
}
],
"propertyNameAtParent": "tradingBots"
@@ -5,10 +5,13 @@
"action": "Add Missing Children",
"label": "Add Missing Children",
"relatedUiObject": "Trading Engine",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Algorithmic-Trading"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -25,19 +28,22 @@
"name": "tradingCurrent",
"type": "node",
"childType": "Trading Current",
"autoAdd": true
"autoAdd": false,
"project": "Foundations"
},
{
"name": "tradingLast",
"type": "node",
"childType": "Trading Last",
"autoAdd": true
"autoAdd": false,
"project": "Foundations"
},
{
"name": "exchangeOrders",
"type": "node",
"childType": "Exchange Orders",
"autoAdd": true
"autoAdd": false,
"project": "Foundations"
}
]
}
@@ -6,23 +6,30 @@
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"iconProject": "Foundations",
"dontShowAtFullscreen": true,
"actionFunction": "uiObject.configEditor.activate"
"actionFunction": "uiObject.configEditor.activate",
"actionProject": "Foundations"
},
{
"action": "Add UI Object",
"label": "Add Trading Bot",
"relatedUiObject": "Trading Bot",
"actionFunction": "payload.executeAction"
"relatedUiObjectProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Add UI Object",
"label": "Add Plotter",
"relatedUiObject": "Plotter",
"actionFunction": "payload.executeAction"
"relatedUiObjectProject": "Foundations",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -45,12 +52,14 @@
{
"name": "tradingBots",
"type": "array",
"childType": "Trading Bot"
"childType": "Trading Bot",
"project": "Algorithmic-Trading"
},
{
"name": "plotters",
"type": "array",
"childType": "Plotter"
"childType": "Plotter",
"project": "Foundations"
}
]
}
@@ -5,7 +5,9 @@
"action": "Add UI Object",
"label": "Add Trading Strategy",
"relatedUiObject": "Trading Strategy",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Add UI Object",
@@ -13,10 +15,13 @@
"propertyToCheckFor": "dynamicIndicators",
"label": "Add Dynamic Indicators",
"relatedUiObject": "Dynamic Indicators",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -33,13 +38,15 @@
"name": "tradingStrategies",
"type": "array",
"childType": "Trading Strategy",
"autoAdd": true
"autoAdd": true,
"project": "Foundations"
},
{
"name": "dynamicIndicators",
"type": "node",
"childType": "Dynamic Indicators",
"autoAdd": true
"autoAdd": true,
"project": "Foundations"
}
]
}
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesExchangeAPI = function (processIndex) {
exports.newAlgorithmicTradingBotModulesExchangeAPI = function (processIndex) {
let MODULE_NAME = "Exchange API";
@@ -1,8 +1,7 @@
exports.newFoundationsBotModulesOrdersCalculations = function (processIndex) {
exports.newAlgorithmicTradingBotModulesOrdersCalculations = function (processIndex) {
/*
When we are live trading, we need to syncronize with the exchange.
*/
const MODULE_NAME = 'Orders Calculations'
let thisObject = {
actualSizeCalculation: actualSizeCalculation,
@@ -1,8 +1,7 @@
exports.newFoundationsBotModulesOrdersSimulations = function (processIndex) {
exports.newAlgorithmicTradingBotModulesOrdersSimulations = function (processIndex) {
/*
When we are backtesting or paper trading, we need to simulate what would have happened at the exchange.
*/
const MODULE_NAME = 'Orders Simulations'
let thisObject = {
actualSizeSimulation: actualSizeSimulation,
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesSnapshots = function(processIndex) {
exports.newAlgorithmicTradingBotModulesSnapshots = function(processIndex) {
/*
This module encapsulates the snapshots functionality.
*/
@@ -1,9 +1,9 @@
exports.newFoundationsBotModulesTradingEngine = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingEngine = function (processIndex) {
/*
We call the Trading Engine to the data structure that is needed in order to exevute the
trading protocol with the specific rules defined at the Trading System.
*/
const MODULE_NAME = 'Trading Engine'
let thisObject = {
mantain: mantain,
reset: reset,
@@ -1,8 +1,7 @@
exports.newFoundationsBotModulesTradingEpisode = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingEpisode = function (processIndex) {
/*
This module packages all functions related to Episodes.
*/
const MODULE_NAME = 'Trading Episode'
let thisObject = {
mantain: mantain,
reset: reset,
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingExecution = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingExecution = function (processIndex) {
/*
The Trading Execution modules manages the execution nodes and execution algoritms.
*/
@@ -16,7 +16,7 @@ exports.newFoundationsBotModulesTradingExecution = function (processIndex) {
let tradingSystem
let sessionParameters
let tradingOrdersModuleObject = TS.projects.foundations.botModules.tradingOrders.newFoundationsBotModulesTradingOrders(processIndex)
let tradingOrdersModuleObject = TS.projects.algorithmicTrading.botModules.tradingOrders.newAlgorithmicTradingBotModulesTradingOrders(processIndex)
return thisObject
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingOrders = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingOrders = function (processIndex) {
/*
The Trading Orders modules manages the execution of orders against the exchanges.
*/
@@ -16,8 +16,8 @@ exports.newFoundationsBotModulesTradingOrders = function (processIndex) {
let tradingSystem
let sessionParameters
let exchangeAPIModuleObject = TS.projects.foundations.botModules.exchangeAPI.newFoundationsBotModulesExchangeAPI(processIndex)
let announcementsModuleObject = TS.projects.foundations.botModules.announcements.newFoundationsBotModulesAnnouncements(processIndex)
let exchangeAPIModuleObject = TS.projects.algorithmicTrading.botModules.exchangeAPI.newAlgorithmicTradingBotModulesExchangeAPI(processIndex)
let announcementsModuleObject = TS.projects.socialBots.botModules.announcements.newSocialBotsBotModulesAnnouncements(processIndex)
return thisObject
@@ -843,7 +843,7 @@ exports.newFoundationsBotModulesTradingOrders = function (processIndex) {
let previousBaseAssetFeesPaid = tradingEngineOrder.orderBaseAsset.feesPaid.value
let previousQuotedAssetFeesPaid = tradingEngineOrder.orderQuotedAsset.feesPaid.value
let ordersSimulationsModuleObject = TS.projects.foundations.botModules.ordersSimulations.newFoundationsBotModulesOrdersSimulations(processIndex)
let ordersSimulationsModuleObject = TS.projects.algorithmicTrading.botModules.ordersSimulations.newAlgorithmicTradingBotModulesOrdersSimulations(processIndex)
ordersSimulationsModuleObject.initialize()
ordersSimulationsModuleObject.actualSizeSimulation(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, applyFeePercentage)
@@ -874,7 +874,7 @@ exports.newFoundationsBotModulesTradingOrders = function (processIndex) {
let previousBaseAssetFeesPaid = tradingEngineOrder.orderBaseAsset.feesPaid.value
let previousQuotedAssetFeesPaid = tradingEngineOrder.orderQuotedAsset.feesPaid.value
let ordersCalculationsModuleObject = TS.projects.foundations.botModules.ordersCalculations.newFoundationsBotModulesOrdersCalculations(processIndex)
let ordersCalculationsModuleObject = TS.projects.algorithmicTrading.botModules.ordersCalculations.newAlgorithmicTradingBotModulesOrdersCalculations(processIndex)
ordersCalculationsModuleObject.initialize()
await ordersCalculationsModuleObject.actualSizeCalculation(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, order, applyFeePercentage)
@@ -1262,7 +1262,7 @@ exports.newFoundationsBotModulesTradingOrders = function (processIndex) {
tradingSystem.highlights.push(executionAlgorithm.id)
tradingSystem.highlights.push(executionNode.id)
announcementsModuleObject.makeAnnoucements(event)
announcementsModuleObject.makeAnnouncements(event)
return situation.name // if the event is triggered, we return the name of the situation that passed
}
}
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingOutput = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingOutput = function (processIndex) {
/*
This module will load if necesary all the data outputs so that they can be appended with new
records if needed. After running the simulation, it will save all the data outputs.
@@ -29,9 +29,9 @@ exports.newFoundationsBotModulesTradingOutput = function (processIndex) {
}
/* Preparing everything for the Simulation */
let tradingSimulationModuleObject = TS.projects.foundations.botModules.tradingSimulation.newFoundationsBotModulesTradingSimulation(processIndex)
let tradingSimulationModuleObject = TS.projects.algorithmicTrading.botModules.tradingSimulation.newAlgorithmicTradingBotModulesTradingSimulation(processIndex)
let outputDatasets = TS.projects.foundations.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
let outputDatasets = TS.projects.visualScripting.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
let outputDatasetsMap = new Map()
await TS.projects.foundations.functionLibraries.outputManagementFunctions.readFiles(
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingPosition = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingPosition = function (processIndex) {
/*
This module packages all functions related to Positions.
*/
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingProcess = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingProcess = function (processIndex) {
/*
This Module will load all the process data dependencies from files and send them downstream.
After execution, will save the time range and status report of the process.
@@ -16,8 +16,8 @@
let dataFiles = new Map()
let multiTimeFrameDataFiles = new Map()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT = TS.projects.foundations.botModules.tradingEngine.newFoundationsBotModulesTradingEngine(processIndex)
let tradingOutputModuleObject = TS.projects.foundations.botModules.tradingOutput.newFoundationsBotModulesTradingOutput(processIndex)
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT = TS.projects.algorithmicTrading.botModules.tradingEngine.newAlgorithmicTradingBotModulesTradingEngine(processIndex)
let tradingOutputModuleObject = TS.projects.algorithmicTrading.botModules.tradingOutput.newAlgorithmicTradingBotModulesTradingOutput(processIndex)
let currentTimeFrame = {}
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingRecords = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingRecords = function (processIndex) {
/*
This module facilitates the appending of records to the output of the process.
*/
@@ -37,7 +37,7 @@ exports.newFoundationsBotModulesTradingRecords = function (processIndex) {
we have a pointer to the node that have the information we need to extract.
Later, based on the product record definition we will extract each individual value.
*/
let outputDatasets = TS.projects.foundations.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
let outputDatasets = TS.projects.visualScripting.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingSimulation = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingSimulation = function (processIndex) {
/*
This Module represents the trading simulacion. Escentially a loop through a set of candles and
the execution at each loop cycle of the Trading System Protocol.
@@ -34,13 +34,13 @@ exports.newFoundationsBotModulesTradingSimulation = function (processIndex) {
'[INFO] runSimulation -> finalDatetime = ' + sessionParameters.timeRange.config.finalDatetime)
/* These are the Modules we will need to run the Simulation */
let tradingRecordsModuleObject = TS.projects.foundations.botModules.tradingRecords.newFoundationsBotModulesTradingRecords(processIndex)
let tradingRecordsModuleObject = TS.projects.algorithmicTrading.botModules.tradingRecords.newAlgorithmicTradingBotModulesTradingRecords(processIndex)
tradingRecordsModuleObject.initialize(outputDatasetsMap)
let tradingSystemModuleObject = TS.projects.foundations.botModules.tradingSystem.newFoundationsBotModulesTradingSystem(processIndex)
let tradingSystemModuleObject = TS.projects.algorithmicTrading.botModules.tradingSystem.newAlgorithmicTradingBotModulesTradingSystem(processIndex)
tradingSystemModuleObject.initialize()
let tradingEpisodeModuleObject = TS.projects.foundations.botModules.tradingEpisode.newFoundationsBotModulesTradingEpisode(processIndex)
let tradingEpisodeModuleObject = TS.projects.algorithmicTrading.botModules.tradingEpisode.newAlgorithmicTradingBotModulesTradingEpisode(processIndex)
tradingEpisodeModuleObject.initialize()
/* Setting up the candles array: The whole simulation is based on the array of candles at the time-frame defined at the session parameters. */
@@ -372,8 +372,8 @@ exports.newFoundationsBotModulesTradingSimulation = function (processIndex) {
}
function positionChart(chart) {
let dataDependencies = TS.projects.foundations.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processDependencies, 'Data Dependency')
dataDependencies = TS.projects.foundations.utilities.nodeFunctions.filterOutNodeWihtoutReferenceParentFromNodeArray(dataDependencies)
let dataDependencies = TS.projects.visualScripting.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processDependencies, 'Data Dependency')
dataDependencies = TS.projects.visualScripting.utilities.nodeFunctions.filterOutNodeWihtoutReferenceParentFromNodeArray(dataDependencies)
/* Finding the Current Element on Daily Files */
if (TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_PROCESSING_DAILY_FILES) {
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingStages = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingStages = function (processIndex) {
/*
This module packages all functions related to Stages.
*/
@@ -21,12 +21,12 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
finalize: finalize
}
let tradingStrategyModuleObject = TS.projects.foundations.botModules.tradingStrategy.newFoundationsBotModulesTradingStrategy(processIndex)
let tradingPositionModuleObject = TS.projects.foundations.botModules.tradingPosition.newFoundationsBotModulesTradingPosition(processIndex)
let tradingExecutionModuleObject = TS.projects.foundations.botModules.tradingExecution.newFoundationsBotModulesTradingExecution(processIndex)
let announcementsModuleObject = TS.projects.foundations.botModules.announcements.newFoundationsBotModulesAnnouncements(processIndex)
let snapshotsModuleObject = TS.projects.foundations.botModules.snapshots.newFoundationsBotModulesSnapshots(processIndex)
let tradingEpisodeModuleObject = TS.projects.foundations.botModules.tradingEpisode.newFoundationsBotModulesTradingEpisode(processIndex)
let tradingStrategyModuleObject = TS.projects.algorithmicTrading.botModules.tradingStrategy.newAlgorithmicTradingBotModulesTradingStrategy(processIndex)
let tradingPositionModuleObject = TS.projects.algorithmicTrading.botModules.tradingPosition.newAlgorithmicTradingBotModulesTradingPosition(processIndex)
let tradingExecutionModuleObject = TS.projects.algorithmicTrading.botModules.tradingExecution.newAlgorithmicTradingBotModulesTradingExecution(processIndex)
let announcementsModuleObject = TS.projects.socialBots.botModules.announcements.newSocialBotsBotModulesAnnouncements(processIndex)
let snapshotsModuleObject = TS.projects.algorithmicTrading.botModules.snapshots.newAlgorithmicTradingBotModulesSnapshots(processIndex)
let tradingEpisodeModuleObject = TS.projects.algorithmicTrading.botModules.tradingEpisode.newAlgorithmicTradingBotModulesTradingEpisode(processIndex)
let tradingEngine
let tradingSystem
@@ -147,8 +147,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
/* Initialize this */
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.triggerOn.value = 1
announcementsModuleObject.makeAnnoucements(triggerStage.triggerOn)
announcementsModuleObject.makeAnnoucements(triggerStage)
announcementsModuleObject.makeAnnouncements(triggerStage.triggerOn)
if (TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
@@ -159,6 +158,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
}
changeStageStatus('Trigger Stage', 'Open')
}
}
}
@@ -194,7 +194,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingSystem.highlights.push(triggerStage.id)
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.triggerOff.value = 1
announcementsModuleObject.makeAnnoucements(triggerStage.triggerOff)
announcementsModuleObject.makeAnnouncements(triggerStage.triggerOff)
changeStageStatus('Trigger Stage', 'Closed', 'Trigger Off Event')
tradingStrategyModuleObject.closeStrategy('Trigger Off')
}
@@ -233,8 +233,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingPositionModuleObject.openPosition(situation.name)
announcementsModuleObject.makeAnnoucements(triggerStage.takePosition)
announcementsModuleObject.makeAnnoucements(strategy.openStage)
announcementsModuleObject.makeAnnouncements(triggerStage.takePosition)
if (TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
@@ -436,7 +435,6 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
/* Now we switch to the Open status. */
changeStageStatus('Manage Stage', 'Open')
announcementsModuleObject.makeAnnoucements(manageStage)
}
}
@@ -487,7 +485,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingPositionModuleObject.applyStopLossFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.tradingCurrent.position.stopLoss.value !== previousValue) {
announcementsModuleObject.makeAnnoucements(phase)
announcementsModuleObject.makeAnnouncements(phase)
}
}
}
@@ -510,7 +508,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingPositionModuleObject.applyTakeProfitFormula(tradingSystem.formulas, phase.formula.id)
if (tradingEngine.tradingCurrent.position.takeProfit.value !== previousValue) {
announcementsModuleObject.makeAnnoucements(phase)
announcementsModuleObject.makeAnnouncements(phase)
}
}
}
@@ -591,7 +589,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingPositionModuleObject.updateStopLoss(tradingEngine.tradingCurrent.position.stopLoss.stopLossPhase.value + 1)
announcementsModuleObject.makeAnnoucements(nextPhaseEvent)
announcementsModuleObject.makeAnnouncements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.nextPhase.value = 1
@@ -642,7 +640,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
continue
}
announcementsModuleObject.makeAnnoucements(moveToPhaseEvent)
announcementsModuleObject.makeAnnouncements(moveToPhaseEvent)
/* Reset this counter */
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.moveToPhase.value = 1
@@ -698,7 +696,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingPositionModuleObject.updateTakeProfit(tradingEngine.tradingCurrent.position.takeProfit.takeProfitPhase.value + 1)
announcementsModuleObject.makeAnnoucements(nextPhaseEvent)
announcementsModuleObject.makeAnnouncements(nextPhaseEvent)
/* Reset this counter */
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.nextPhase.value = 1
@@ -749,7 +747,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
continue
}
announcementsModuleObject.makeAnnoucements(moveToPhaseEvent)
announcementsModuleObject.makeAnnouncements(moveToPhaseEvent)
/* Reset this counter */
tradingEngine.tradingCurrent.tradingEpisode.distanceToTradingEvent.moveToPhase.value = 1
@@ -762,54 +760,50 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
}
function checkStopLossOrTakeProfitWasHit() {
{
let strategy = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value]
/*
Checking what happened since the last execution. We need to know if the Stop Loss
or our Take Profit were hit.
*/
let strategy = tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value]
/*
Checking what happened since the last execution. We need to know if the Stop Loss
or our Take Profit were hit.
*/
/* Stop Loss condition: Here we verify if the Stop Loss was hit or not. */
if (
(
tradingEngine.tradingCurrent.position.stopLoss.stopLossPosition.value === 'Above' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.max.value >= tradingEngine.tradingCurrent.position.stopLoss.value
) ||
(
tradingEngine.tradingCurrent.position.stopLoss.stopLossPosition.value === 'Below' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.min.value <= tradingEngine.tradingCurrent.position.stopLoss.value
)
) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
/* Stop Loss condition: Here we verify if the Stop Loss was hit or not. */
if (
(
tradingEngine.tradingCurrent.position.stopLoss.stopLossPosition.value === 'Above' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.max.value >= tradingEngine.tradingCurrent.position.stopLoss.value
) ||
(
tradingEngine.tradingCurrent.position.stopLoss.stopLossPosition.value === 'Below' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.min.value <= tradingEngine.tradingCurrent.position.stopLoss.value
)
) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Stop Loss was hit.')
tradingPositionModuleObject.closingPosition('Stop Loss')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed', 'Stop Loss Hit')
announcementsModuleObject.makeAnnoucements(strategy.closeStage)
return
}
/* Take Profit condition: Here we verify if the Take Profit was hit or not. */
if (
(
tradingEngine.tradingCurrent.position.takeProfit.takeProfitPosition.value === 'Below' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.min.value <= tradingEngine.tradingCurrent.position.takeProfit.value
) ||
(
tradingEngine.tradingCurrent.position.takeProfit.takeProfitPosition.value === 'Above' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.max.value >= tradingEngine.tradingCurrent.position.takeProfit.value
)
) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
tradingPositionModuleObject.closingPosition('Take Profit')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed', 'Take Profit Hit')
announcementsModuleObject.makeAnnoucements(strategy.closeStage)
return
}
tradingPositionModuleObject.closingPosition('Stop Loss')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed', 'Stop Loss Hit')
return
}
/* Take Profit condition: Here we verify if the Take Profit was hit or not. */
if (
(
tradingEngine.tradingCurrent.position.takeProfit.takeProfitPosition.value === 'Below' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.min.value <= tradingEngine.tradingCurrent.position.takeProfit.value
) ||
(
tradingEngine.tradingCurrent.position.takeProfit.takeProfitPosition.value === 'Above' &&
tradingEngine.tradingCurrent.tradingEpisode.candle.max.value >= tradingEngine.tradingCurrent.position.takeProfit.value
)
) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] checkStopLossOrTakeProfitWasHit -> Take Profit was hit.')
tradingPositionModuleObject.closingPosition('Take Profit')
changeStageStatus('Close Stage', 'Opening')
changeStageStatus('Manage Stage', 'Closed', 'Take Profit Hit')
return
}
return
}
}
}
@@ -1114,7 +1108,7 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
tradingSystem.highlights.push(closeStageEvent.id)
tradingSystem.highlights.push(stage.id)
announcementsModuleObject.makeAnnoucements(closeStageEvent)
announcementsModuleObject.makeAnnouncements(closeStageEvent)
return true
}
}
@@ -1148,9 +1142,11 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
if (stage.status.value === 'Open') {
openStage(stage)
checkUserDefinedCode(stageName, 'Open')
checkAnnounce(stageName, 'Open')
}
if (stage.status.value === 'Closed') {
checkUserDefinedCode(stageName, 'Closed')
checkAnnounce(stageName, 'Closed')
closeStage(stage, stageName)
}
@@ -1186,7 +1182,6 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
if (stageName === 'Close Stage') {
if (tradingEngine.tradingCurrent.position.status.value === 'Open') {
tradingPositionModuleObject.closingPosition('Close Stage Closed')
/* NOTE:TODO: Announcement May need added Here */
}
}
}
@@ -1271,33 +1266,41 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
/* checkUserDefinedCode(): Checks if User Defined Code exists and processes if applicable. */
function checkUserDefinedCode(stage, status, when) {
let tradingSystemStage = getTradingSystemStage(stage);
let tradingSystemStage = getTradingSystemStage(stage);
if (tradingSystemStage !== undefined &&
tradingSystemStage.userDefinedCode !== undefined) {
if (status === 'Running' && when !== tradingSystemStage.userDefinedCode.config.whileAtStageWhenToRun) { return; }
if (tradingSystemStage !== undefined &&
tradingSystemStage.userDefinedCode !== undefined) {
if (status === 'Running' && when !== tradingSystemStage.userDefinedCode.config.whileAtStageWhenToRun) { return; }
switch(status) {
case 'Open' : {
if (tradingSystemStage.userDefinedCode.config.runWhenEnteringStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
switch(status) {
case 'Open' : {
if (tradingSystemStage.userDefinedCode.config.runWhenEnteringStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
}
break;
}
case 'Running' : {
if (tradingSystemStage.userDefinedCode.config.runWhileAtStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
}
break;
}
case 'Closed' : {
if (tradingSystemStage.userDefinedCode.config.runWhenExitingStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
}
break;
}
}
break;
}
case 'Running' : {
if (tradingSystemStage.userDefinedCode.config.runWhileAtStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
}
break;
}
case 'Closed' : {
if (tradingSystemStage.userDefinedCode.config.runWhenExitingStage) {
tradingSystem.evalUserCode(tradingSystemStage, 'User Defined Code');
}
break;
}
}
}
}
// checkAnnounce(): Check if stage announcement should be made
function checkAnnounce(stage, status) {
let tradingSystemStage = getTradingSystemStage(stage);
if (status === 'Open' || status === 'Closed') {
announcementsModuleObject.makeAnnouncements(tradingSystemStage, status)
}
}
/* getTradingSystemStage(): takes stage name returns stage object. */
@@ -1321,4 +1324,4 @@ exports.newFoundationsBotModulesTradingStages = function (processIndex) {
}
}
}
}
}
@@ -1,8 +1,8 @@
exports.newFoundationsBotModulesTradingStrategy = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingStrategy = function (processIndex) {
/*
This module packages all functions related to Strategies.
*/
const MODULE_NAME = 'Trading Strategy'
let thisObject = {
mantain: mantain,
reset: reset,
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingSystem = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingSystem = function (processIndex) {
/*
The Trading System is the user defined set of rules compliant with the Trading Protocol that
defines the trading logic to be applied during each cycle of the Simulation.
@@ -26,7 +26,7 @@ exports.newFoundationsBotModulesTradingSystem = function (processIndex) {
let sessionParameters
let dynamicIndicators
let tradingStagesModuleObject = TS.projects.foundations.botModules.tradingStages.newFoundationsBotModulesTradingStages(processIndex)
let tradingStagesModuleObject = TS.projects.algorithmicTrading.botModules.tradingStages.newAlgorithmicTradingBotModulesTradingStages(processIndex)
let taskParameters = {
market: TS.projects.foundations.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName +
@@ -1,8 +1,8 @@
exports.newFoundationsBotModulesSingleMarketTradingBot = function (processIndex) {
exports.newAlgorithmicTradingBotModulesSingleMarketTradingBot = function (processIndex) {
const MODULE_NAME = "Single Market Trading Bot";
let session = TS.projects.foundations.botModules.tradingSession.newFoundationsBotModulesTradingSession(processIndex)
let session = TS.projects.algorithmicTrading.botModules.tradingSession.newAlgorithmicTradingBotModulesTradingSession(processIndex)
let nextLoopTimeoutHandle;
let thisObject = {
@@ -282,7 +282,7 @@
"[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well.")
switch (TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.framework.name) {
case 'Low-Frequency-Trading-Process': {
processFramework = TS.projects.foundations.botModules.tradingProcess.newFoundationsBotModulesTradingProcess(processIndex);
processFramework = TS.projects.algorithmicTrading.botModules.tradingProcess.newAlgorithmicTradingBotModulesTradingProcess(processIndex);
startProcessFramework();
break;
}
@@ -1,4 +1,4 @@
exports.newFoundationsBotModulesTradingSession = function (processIndex) {
exports.newAlgorithmicTradingBotModulesTradingSession = function (processIndex) {
const MODULE_NAME = "Trading Session"
@@ -7,7 +7,7 @@
}
TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SOCIAL_BOTS_MODULE =
TS.projects.foundations.botModules.socialBots.newFoundationsBotModulesSocialBots(processIndex)
TS.projects.socialBots.botModules.socialBots.newSocialBotsBotModulesSocialBots(processIndex)
return thisObject;
@@ -0,0 +1,42 @@
function newAlgorithmicTradingActionSwitch() {
let thisObject = {
executeAction: executeAction,
initialize: initialize,
finalize: finalize
}
return thisObject
function finalize() {
}
function initialize() {
/* Nothing to initialize since a Function Library does not hold any state. */
}
async function executeAction(action) {
switch (action.name) {
case 'Run Trading Session':
{
UI.projects.algorithmicTrading.functionLibraries.tradingSessionFunctions.runSession(action.node, false, action.callBackFunction)
}
break
case 'Resume Trading Session':
{
UI.projects.algorithmicTrading.functionLibraries.tradingSessionFunctions.runSession(action.node, true, action.callBackFunction)
}
break
case 'Stop Trading Session':
{
UI.projects.algorithmicTrading.functionLibraries.tradingSessionFunctions.stopSession(action.node, action.callBackFunction)
}
break
default: {
console.log("[WARN] Action sent to Algorithmic-Trading Action Switch does not belong here. Verify at the App Schema file of the node that triggered this action that the actionProject is pointing to the right project. -> Action = " + action.name + " -> Action Node Name = " + action.node.name)
}
}
}
}
@@ -1,4 +1,4 @@
function newFoundationsFunctionLibraryTradingSessionFunctions() {
function newAlgorithmicTradingFunctionLibraryTradingSessionFunctions() {
let thisObject = {
syncronizeSessionWithBackEnd: syncronizeSessionWithBackEnd,
runSession: runSession,
@@ -110,7 +110,7 @@ function newFoundationsFunctionLibraryTradingSessionFunctions() {
'Simulated Exchange Events->Simulated Partial Fill->Simulated Actual Rate->Simulated Fees Paid->Formula->' +
'User Defined Code->Javascript Code->'
let tradingSystem = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node.tradingSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath)
let tradingSystem = UI.projects.visualScripting.functionLibraries.protocolNode.getProtocolNode(node.tradingSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath)
lightingPath = '' +
'Trading Engine->' +
@@ -149,7 +149,7 @@ function newFoundationsFunctionLibraryTradingSessionFunctions() {
'Index->Situation Name->Formula->Periods->' +
'User Defined Variables->User Defined Variable->'
let tradingEngine = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node.tradingEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath)
let tradingEngine = UI.projects.visualScripting.functionLibraries.protocolNode.getProtocolNode(node.tradingEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath)
lightingPath = '' +
'Backtesting Session->Paper Trading Session->Forward Testing Session->Live Trading Session->' +
@@ -159,13 +159,13 @@ function newFoundationsFunctionLibraryTradingSessionFunctions() {
'Social Bot Command->Formula->' +
'Exchange Account Asset->Asset->'
let session = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
let session = UI.projects.visualScripting.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
let defaultExchange = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.exchange.payload, 'codeName')
let defaultExchange = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(validationsResult.exchange.payload, 'codeName')
let defaultMarket =
UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.market.baseAsset.payload.referenceParent.payload, 'codeName')
UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(validationsResult.market.baseAsset.payload.referenceParent.payload, 'codeName')
+ '-' +
UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.market.quotedAsset.payload.referenceParent.payload, 'codeName')
UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(validationsResult.market.quotedAsset.payload.referenceParent.payload, 'codeName')
let dependencyFilter = UI.projects.foundations.functionLibraries.dependenciesFilter.createDependencyFilter(
defaultExchange,
@@ -266,7 +266,7 @@ function newFoundationsFunctionLibraryTradingSessionFunctions() {
return
}
result.lanNetworkNode = UI.projects.foundations.utilities.meshes.findNodeInNodeMesh(result.taskManager, 'LAN Network Node', undefined, true, false, true, false)
result.lanNetworkNode = UI.projects.visualScripting.utilities.meshes.findNodeInNodeMesh(result.taskManager, 'LAN Network Node', undefined, true, false, true, false)
if (node.tradingSystemReference === undefined) {
node.payload.uiObject.setErrorMessage('Session needs a child Trading System Reference.')
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

@@ -1,4 +1,4 @@
exports.newFoundationsUtilitiesPlugins = function () {
exports.newPluginsUtilitiesPlugins = function () {
let thisObject = {
getPluginFileNames: getPluginFileNames,
@@ -14,7 +14,7 @@ exports.newFoundationsUtilitiesPlugins = function () {
SA.nodeModules.fs.readdir(path, (err, files) => {
if (err) {
reject()
reject(err)
return
}
if (files === undefined) {
@@ -8,10 +8,13 @@
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "API Map",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Data Mine",
"actionFunction": "payload.executeAction"
"iconPathOn": "data-mine",
"iconPathOff": "data-mine",
"iconProject": "Data-Mining",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -31,7 +35,8 @@
"name": "pluginFiles",
"type": "array",
"childType": "Plugin File",
"autoAdd": false
"autoAdd": false,
"project": "Foundations"
}
]
}
@@ -3,6 +3,7 @@
"menuItems": [
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -6,7 +6,8 @@
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
"actionFunction": "uiObject.configEditor.activate",
"actionProject": "Foundations"
},
{
"action": "Add UI Object",
@@ -14,28 +15,37 @@
"propertyToCheckFor": "pluginFilePosition",
"actionFunction": "payload.executeAction",
"label": "Add Plugin File Position",
"relatedUiObject": "Plugin File Position"
"relatedUiObject": "Plugin File Position",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Enable Saving With Workspace",
"actionFunction": "payload.executeAction",
"label": "Enable Saving With Workspace",
"relatedUiObject": "Plugin File"
"relatedUiObject": "Plugin File",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Disable Saving With Workspace",
"actionFunction": "payload.executeAction",
"label": "Disable Saving With Workspace",
"relatedUiObject": "Plugin File"
"relatedUiObject": "Plugin File",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Save Plugin",
"actionFunction": "payload.executeAction",
"label": "Save Plugin",
"relatedUiObject": "Plugin File"
"relatedUiObject": "Plugin File",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Learning Engine",
"actionFunction": "payload.executeAction"
"iconPathOn": "learning-engine",
"iconPathOff": "learning-engine",
"iconProject": "Machine-Learning",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Learning Mine",
"actionFunction": "payload.executeAction"
"iconPathOn": "learning-mine",
"iconPathOff": "learning-mine",
"iconProject": "Machine-Learning",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Learning System",
"actionFunction": "payload.executeAction"
"iconPathOn": "learning-system",
"iconPathOff": "learning-system",
"iconProject": "Machine-Learning",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -6,16 +6,20 @@
"actionFunction": "uiObject.configEditor.activate",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration"
"iconPathOff": "configuration",
"actionProject": "Foundations"
},
{
"action": "Add Missing Plugin Types",
"label": "Add Missing Plugin Types",
"relatedUiObject": "Plugins",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Trading Engine",
"actionFunction": "payload.executeAction"
"iconPathOn": "trading-engine",
"iconPathOff": "trading-engine",
"iconProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Trading Mine",
"actionFunction": "payload.executeAction"
"iconPathOn": "trading-mine",
"iconPathOff": "trading-mine",
"iconProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -7,11 +7,15 @@
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Trading System",
"actionFunction": "payload.executeAction"
"iconPathOn": "trading-system",
"iconPathOff": "trading-system",
"iconProject": "Algorithmic-Trading",
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -9,10 +9,13 @@
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Tutorial",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Education"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
@@ -0,0 +1,46 @@
{
"type": "Plugins Project",
"menuItems": [
{
"action": "Add Missing Children",
"label": "Add Missing Children",
"relatedUiObject": "Foundations Project",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting",
"relatedUiObjectProject": "Foundations"
},
{
"action": "Add UI Object",
"label": "Add Plugins",
"relatedUiObject": "Plugins",
"relatedUiObjectProject": "Community-Plugins",
"actionFunction": "payload.executeAction",
"actionProject": "Visual-Scripting"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"actionFunction": "payload.executeAction",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity"
}
],
"isProjectHead": true,
"isTitleAllwaysVisible": false,
"addLeftIcons": true,
"isPinned": true,
"positionLocked": true,
"icon": "plugins-project",
"childrenNodesProperties": [
{
"name": "projectDefinition",
"type": "node",
"childType": "Project Definition",
"project": "Foundations",
"autoAdd": true
}
]
}
@@ -8,10 +8,13 @@
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Plugin Project",
"actionFunction": "payload.executeAction"
"actionFunction": "payload.executeAction",
"actionProject": "Community-Plugins",
"relatedUiObjectProject": "Community-Plugins"
},
{
"action": "Delete UI Object",
"actionProject": "Visual-Scripting",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"actionFunction": "payload.executeAction",
@@ -0,0 +1,102 @@
function newCommunityPluginsActionSwitch() {
let thisObject = {
executeAction: executeAction,
initialize: initialize,
finalize: finalize
}
return thisObject
function finalize() {
}
function initialize() {
/* Nothing to initialize since a Function Library does not hold any state. */
}
async function executeAction(action) {
switch (action.name) {
case 'Install as Plugin':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.installAsPlugin(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Projects':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginProjects(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Types':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTypes(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Data Mines':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginDataMines(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Trading Mines':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTradingMines(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Trading Systems':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTradingSystems(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Trading Engines':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTradingEngines(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Learning Mines':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginLearningMines(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Learning Systems':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginLearningSystems(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Learning Engines':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginLearningEngines(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin Tutorials':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginTutorials(action.node, action.rootNodes)
}
break
case 'Add Missing Plugin API Maps':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.addMissingPluginApiMaps(action.node, action.rootNodes)
}
break
case 'Enable Saving With Workspace':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.enableSavingWithWorkspace(action.node, action.rootNodes)
}
break
case 'Disable Saving With Workspace':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.disableSavingWithWorkspace(action.node, action.rootNodes)
}
break
case 'Save Plugin':
{
UI.projects.communityPlugins.functionLibraries.pluginsFunctions.savePlugin(action.node, action.rootNodes)
}
break
default: {
console.log("[WARN] Action sent to Community-Plugins Action Switch does not belong here. Verify at the App Schema file of the node that triggered this action that the actionProject is pointing to the right project. -> Action = " + action.name + " -> Action Node Name = " + action.node.name)
}
}
}
}
@@ -1,4 +1,4 @@
function newFoundationsFunctionLibraryPluginsFunctions() {
function newPluginsFunctionLibraryPluginsFunctions() {
let thisObject = {
addMissingPluginProjects: addMissingPluginProjects,
addMissingPluginTypes: addMissingPluginTypes,
@@ -22,8 +22,8 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
for (let k = 0; k < PROJECTS_SCHEMA.length; k++) {
let projectDefinition = PROJECTS_SCHEMA[k]
let project = projectDefinition.name
if (UI.projects.foundations.utilities.nodeChildren.isMissingChildrenByName(node, project) === true) {
let child = UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject(node, 'Plugin Project')
if (UI.projects.visualScripting.utilities.nodeChildren.isMissingChildrenByName(node, project) === true) {
let child = UI.projects.visualScripting.functionLibraries.uiObjectsFromNodes.addUIObject(node, 'Plugin Project')
child.name = project
let config = JSON.parse(child.config)
config.codeName = project
@@ -33,7 +33,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
function addMissingPluginTypes(node, rootNodes) {
let project = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'codeName')
let project = UI.projects.visualScripting.utilities.nodeConfig.loadConfigProperty(node.payload, 'codeName')
if (project === undefined || project === "") { return }
for (let k = 0; k < PROJECTS_SCHEMA.length; k++) {
let projectDefinition = PROJECTS_SCHEMA[k]
@@ -42,15 +42,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
for (let i = 0; i < projectDefinition.plugins.length; i++) {
let pluginType = "Plugin" + " " + projectDefinition.plugins[i]
if (UI.projects.foundations.utilities.nodeChildren.isMissingChildrenByType(node, pluginType) === true) {
UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject(node, pluginType, undefined, project)
if (UI.projects.visualScripting.utilities.nodeChildren.isMissingChildrenByType(node, pluginType) === true) {
UI.projects.visualScripting.functionLibraries.uiObjectsFromNodes.addUIObject(node, pluginType, undefined, 'Community-Plugins')
}
}
}
}
function addMissingPluginDataMines(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -58,15 +58,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Data-Mines', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Data-Mines', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Data-Mines', 'Data Mine')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Data-Mines', 'Data Mine', 'Data-Mining')
}
}
function addMissingPluginTradingMines(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -74,15 +74,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Mines', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Trading-Mines', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Mines', 'Trading Mine')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Mines', 'Trading Mine', 'Algorithmic-Trading')
}
}
function addMissingPluginTradingSystems(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -90,15 +90,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Systems', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Trading-Systems', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Systems', 'Trading System')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Systems', 'Trading System', 'Algorithmic-Trading')
}
}
function addMissingPluginTradingEngines(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -106,15 +106,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Engines', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Trading-Engines', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Engines', 'Trading Engine')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Engines', 'Trading Engine', 'Algorithmic-Trading')
}
}
function addMissingPluginLearningMines(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -122,15 +122,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Mines', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Learning-Mines', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Mines', 'Learning Mine')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Mines', 'Learning Mine', 'Machine-Learning')
}
}
function addMissingPluginLearningSystems(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -138,15 +138,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Systems', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Learning-Systems', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Systems', 'Learning System')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Systems', 'Learning System', 'Machine-Learning')
}
}
function addMissingPluginLearningEngines(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -154,15 +154,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Engines', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Learning-Engines', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Engines', 'Learning Engine')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Engines', 'Learning Engine', 'Machine-Learning')
}
}
function addMissingPluginTutorials(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -170,15 +170,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Tutorials', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'Tutorials', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Tutorials', 'Tutorial')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Tutorials', 'Tutorial', 'Education')
}
}
function addMissingPluginApiMaps(node, rootNodes) {
let projectName = UI.projects.foundations.utilities.plugins.getProjectName(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.")
@@ -186,34 +186,34 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
}
}
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'API-Maps', onNamesArrived)
UI.projects.communityPlugins.utilities.plugins.getPluginFileNames(projectName, 'API-Maps', onNamesArrived)
function onNamesArrived(fileNames) {
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'API-Maps', 'API Map')
UI.projects.communityPlugins.utilities.plugins.addMissingPluginFiles(node, fileNames, 'API-Maps', 'API Map', 'Foundations')
}
}
function enableSavingWithWorkspace(node, rootNodes) {
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'saveWithWorkspace', true)
UI.projects.visualScripting.utilities.nodeConfig.saveConfigProperty(node.payload, 'saveWithWorkspace', true)
node.payload.uiObject.setInfoMessage('Saving with Workspace Enabled')
}
function disableSavingWithWorkspace(node, rootNodes) {
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'saveWithWorkspace', false)
UI.projects.visualScripting.utilities.nodeConfig.saveConfigProperty(node.payload, 'saveWithWorkspace', false)
node.payload.uiObject.setInfoMessage('Saving with Workspace Disabled')
}
function savePlugin(node, rootNodes) {
UI.projects.foundations.utilities.plugins.savePluginFile(node)
UI.projects.communityPlugins.utilities.plugins.savePluginFile(node)
}
function installAsPlugin(node, rootNodes) {
let plugins = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadByNodeType('Plugins')
let pluginProject = UI.projects.foundations.utilities.nodeChildren.findChildByCodeName(plugins, node.project)
let pluginFolderName = UI.projects.foundations.utilities.plugins.getPluginFolderNamesByNodeType(node.type)
let pluginProject = UI.projects.visualScripting.utilities.nodeChildren.findChildByCodeName(plugins, node.project)
let pluginFolderName = UI.projects.communityPlugins.utilities.plugins.getPluginFolderNamesByNodeType(node.type)
let pluginForlderNodeType = 'Plugin ' + pluginFolderName.replaceAll('-', ' ')
let pluginFolderNode = UI.projects.foundations.utilities.nodeChildren.findChildByType(pluginProject, pluginForlderNodeType)
let pluginFile = UI.projects.foundations.utilities.plugins.addMissingPluginFile(pluginFolderNode, node.name, pluginFolderName, node.type, true)
let pluginFolderNode = UI.projects.visualScripting.utilities.nodeChildren.findChildByType(pluginProject, pluginForlderNodeType)
let pluginFile = UI.projects.communityPlugins.utilities.plugins.addMissingPluginFile(pluginFolderNode, node.name, pluginFolderName, node.type, node.project, true)
node.isPlugin = true
if (pluginFile === undefined) {
@@ -221,6 +221,6 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
return
}
UI.projects.foundations.utilities.plugins.savePluginFile(pluginFile)
UI.projects.communityPlugins.utilities.plugins.savePluginFile(pluginFile)
}
}
Loaded 100 of 1129 files, more files were not shown because too many files have changed in this diff. Show more