apply some changes to Pack npm scripts for support Pack and Compile Workspace ...

add XCHVWAP Indicator, extends it's Helper class and implement it's usage inside XCH strategy ...
This commit is contained in:
2024-08-03 06:14:47 +03:30
parent 8478e458c2
commit f7040490c8
17 changed files with 7689 additions and 3960 deletions
File diff suppressed because it is too large Load Diff
+506
View File
@@ -0,0 +1,506 @@
/**
* XColor Tools Module ...
* a module for handle colorify text contents in node js ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
//#region Module Imports ...
const XValueTools = require("./x-value.tools");
//#endregion
//
//#region Constants ...
/**
* these are available style which can applied to an string ...
*/
const AVAILABLE_STYLES = {
//
Bold: "\x1b[1m",
Dim: "\x1b[2m",
Underlined: "\x1b[4m",
Blink: "\x1b[5m",
ReverseFandB: "\x1b[7m",
Hidden: "\x1b[8m",
//
// Commonly used for reset all Styles ...
Reset: "\x1b[0m"
};
/**
* these are available foreground colors which can applied to an string ...
*/
const AVAILABLE_FOREGROUND_COLORS = {
Default: "\x1b[39m",
Black: "\x1b[30m",
Red: "\x1b[31m",
Green: "\x1b[32m",
Yellow: "\x1b[33m",
Blue: "\x1b[34m",
Magenta: "\x1b[35m",
Cyan: "\x1b[36m",
LightGray: "\x1b[37m",
DarkGray: "\x1b[90m",
LightRed: "\x1b[91m",
LightGreen: "\x1b[92m",
LightYellow: "\x1b[93m",
LightBlue: "\x1b[94m",
LightMagenta: "\x1b[95m",
LightCyan: "\x1b[96m",
White: "\x1b[97m",
};
/**
* these are available background colors which can applied to an string ...
*/
const AVAILABLE_BACKGROUND_COLORS = {
Default: "\x1b[49m",
Black: "\x1b[40m",
Red: "\x1b[41m",
Green: "\x1b[42m",
Yellow: "\x1b[43m",
Blue: "\x1b[44m",
Magenta: "\x1b[45m",
Cyan: "\x1b[46m",
LightGray: "\x1b[47m",
DarkGray: "\x1b[100m",
LightRed: "\x1b[101m",
LightGreen: "\x1b[102m",
LightYellow: "\x1b[103m",
LightBlue: "\x1b[104m",
LightMagenta: "\x1b[105m",
LightCyan: "\x1b[106m",
White: "\x1b[107m",
};
/**
* these are available style names, which exports from module and
* users can use them ...
*/
const STYLE_NAMES = {
Bold: "Bold",
Dim: "Dim",
Underlined: "Underlined",
Blink: "Blink",
ReverseFandB: "ReverseFandB",
Hidden: "Hidden",
Reset: "Reset",
};
/**
* these are available color names, which exports from module and
* users can use them ...
*/
const COLOR_NAMES = {
Default: "Default",
Black: "Black",
Red: "Red",
Green: "Green",
Yellow: "Yellow",
Blue: "Blue",
Magenta: "Magenta",
Cyan: "Cyan",
LightGray: "LightGray",
DarkGray: "DarkGray",
LightRed: "LightRed",
LightGreen: "LightGreen",
LightYellow: "LightYellow",
LightBlue: "LightBlue",
LightMagenta: "LightMagenta",
LightCyan: "LightCyan",
White: "White",
};
//#endregion
//
//#region Actions ...
/**
* apply specified style and color on a content ...
*
* @param {string} content specified content for styling ...
* @param {string} color specific color name for using to styling ...
* @param {string} style soecufic style name to use ...
* @param {boolean} toForeground apply specified color as foreground ...
* @param {boolean} toBackground apply specified color as background ...
* @returns {string} styled content ...
*/
function apply(
content,
color,
style,
toForeground = true,
toBackground = false
) {
//
let result = content;
//
// Validate Arg ...
if (!XValueTools.isValidArg(content)) {
return result;
}
//
// Detect and Validate Style and Apply it ...
let eStyle = AVAILABLE_STYLES[style];
if (XValueTools.isValidArg(eStyle)) {
result = `${eStyle}${result}${AVAILABLE_STYLES.Reset}`;
}
//
// Detect and Validate Foreground Color and Apply it ...
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
if (
!!toForeground
&& XValueTools.isValidArg(eFColor)
) {
result = `${eFColor}${result}${AVAILABLE_STYLES.Reset}`;
}
//
// Detect and Validate Background Color and Apply it ...
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
if (
!!toBackground
&& XValueTools.isValidArg(eBColor)
) {
result = `${eBColor}${result}${AVAILABLE_STYLES.Reset}`;
}
}
/**
* apply specific style on a content ...
*
* @param {string} content specific content which going to styled ...
* @param {string} style a member of STYLE_NAMES which specified that which style going to applied to content ...
* @returns {string} styled content ...
*/
function applyStyle(content, style) {
//
// Validate Arg ...
if (!XValueTools.isValidArg(content)) {
return content;
}
//
let eStyle = AVAILABLE_STYLES[style];
if (eStyle === undefined) {
return content;
}
//
return `${eStyle}${content}${AVAILABLE_STYLES.Reset}`;
}
/**
* apply specific foreground color on a content ...
*
* @param {string} content specific content which going to colorified ...
* @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ...
* @returns {string} colorified content ...
*/
function applyForegroundColor(content, color) {
//
// Validate Arg ...
if (!XValueTools.isValidArg(content)) {
return content;
}
//
let eColor = AVAILABLE_FOREGROUND_COLORS[color];
if (eColor === undefined) {
return content;
}
//
return `${eColor}${content}${AVAILABLE_STYLES.Reset}`;
}
/**
* apply specific background color on a content ...
*
* @param {string} content specific content which going to colorified ...
* @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ...
* @returns {string} colorified content ...
*/
function applyBackgroundColor(content, color) {
//
// Validate Arg ...
if (!XValueTools.isValidArg(content)) {
return content;
}
//
let eColor = AVAILABLE_BACKGROUND_COLORS[color];
if (eColor === undefined) {
return content;
}
//
return `${eColor}${content}${AVAILABLE_STYLES.Reset}`;
}
/**
* generate style and color applier expression ...
*
* @param {string} color specific color name for using to styling ...
* @param {string} style soecufic style name to use ...
* @param {boolean} reset close applier string by reset styles ...
* @param {boolean} toForeground apply specified color as foreground ...
* @param {boolean} toBackground apply specified color as background ...
* @returns {string} style and color applier string ...
*/
function getApplier(
style = "",
color = "",
reset = false,
toForeground = true,
toBackground = false
) {
//
let result = "";
//
// Detect and Validate Style and Apply it ...
let eStyle = AVAILABLE_STYLES[style];
if (XValueTools.isValidArg(eStyle)) {
result = `${eStyle}`;
}
//
// Detect and Validate Foreground Color and Apply it ...
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
if (
!!toForeground
&& XValueTools.isValidArg(eFColor)
) {
result = `${eFColor}`;
}
//
// Detect and Validate Background Color and Apply it ...
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
if (
!!toBackground
&& XValueTools.isValidArg(eBColor)
) {
result = `${eBColor}`;
}
//
if (
!!reset &&
result.length > 0
) {
result = `${result}${AVAILABLE_STYLES.Reset}`;
}
//
return result;
}
/**
* generate style applier expression ...
*
* @param {string} style soecufic style name to use ...
* @param {boolean} reset close applier string by reset styles ...
* @returns {string} style applier string ...
*/
function getStyleApplier(
style = "",
reset = false
) {
//
let result = "";
//
// Detect and Validate Style and Apply it ...
let eStyle = AVAILABLE_STYLES[style];
if (XValueTools.isValidArg(eStyle)) {
result = `${eStyle}`;
}
//
if (
!!reset &&
result.length > 0
) {
result = `${result}${AVAILABLE_STYLES.Reset}`;
}
//
return result;
}
/**
* generate color applier expression ...
*
* @param {string} color specific color name for using to styling ...
* @param {boolean} reset close applier string by reset styles ...
* @param {boolean} toForeground apply specified color as foreground ...
* @param {boolean} toBackground apply specified color as background ...
* @returns {string} color applier string ...
*/
function getColorApplier(
color = "",
reset = false,
toForeground = true,
toBackground = false
) {
//
let result = "";
//
// Detect and Validate Foreground Color and Apply it ...
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
if (
!!toForeground
&& XValueTools.isValidArg(eFColor)
) {
result = `${eFColor}`;
}
//
// Detect and Validate Background Color and Apply it ...
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
if (
!!toBackground
&& XValueTools.isValidArg(eBColor)
) {
result = `${eBColor}`;
}
//
if (
!!reset &&
result.length > 0
) {
result = `${result}${AVAILABLE_STYLES.Reset}`;
}
//
return result;
}
/**
* colorified specific content ...
*
* @param {string} content specified content for styling ...
* @param {string} color specific color name for using to styling ...
* @param {boolean} toForeground apply specified color as foreground ...
* @param {boolean} toBackground apply specified color as background ...
* @returns {string}
*/
function colorifyContent(
content = "",
color = "",
toForeground = true,
toBackground = false
) {
//
let result = content;
//
if (!XValueTools.isValidArg(content)) {
return result;
}
//
// Finde Colors ...
//
// Detect and Validate Foreground Color and Apply it ...
let eFColor = AVAILABLE_FOREGROUND_COLORS[color];
if (
!!toForeground
&& XValueTools.isValidArg(eFColor)
) {
result = `${eFColor}${result}`;
}
//
// Detect and Validate Background Color and Apply it ...
let eBColor = AVAILABLE_BACKGROUND_COLORS[color];
if (
!!toBackground
&& XValueTools.isValidArg(eBColor)
) {
result = `${eBColor}${result}`;
}
//
if (
result.length > 0
&& (
XValueTools.isValidArg(eFColor) ||
XValueTools.isValidArg(eBColor)
)
) {
result = `${result}${AVAILABLE_STYLES.Reset}`;
}
//
return result;
}
/**
* apply style on specific content ...
*
* @param {string} content specified content for styling ...
* @param {string} style soecufic style name to use ...
* @returns {string}
*/
function stylifiyContent(
content = "",
style = "",
) {
//
let result = content;
//
if (!XValueTools.isValidArg(content)) {
return result;
}
//
// Detect and Validate Style and Apply it ...
let eStyle = AVAILABLE_STYLES[style];
if (XValueTools.isValidArg(eStyle)) {
result = `${eStyle}${result}`;
}
//
if (
result.length > 0
&& XValueTools.isValidArg(eStyle)
) {
result = `${result}${AVAILABLE_STYLES.Reset}`;
}
//
return result;
}
//#endregion
//
//#region Module Exports ...
module.exports = {
//
STYLE_NAMES,
COLOR_NAMES,
//
apply,
applyStyle,
getApplier,
getColorApplier,
getStyleApplier,
colorifyContent,
stylifiyContent,
applyForegroundColor,
applyBackgroundColor,
}
//#endregion
+890
View File
@@ -0,0 +1,890 @@
/**
* XFile Tools Module ...
* a module for handle all file/folder manipulating task in node js ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
//#region Module Imports ...
const fs = require('fs');
const os = require('os');
const Path = require('path');
const http = require('http');
const https = require('https');
const XValueTools = require('./x-value.tools');
//#endregion
//
//#region Constants ...
/**
* current os path separators ...
*/
const PathSeparator = Path.sep;
/**
* current directory ...
*/
const CurrentDir = __dirname;
//#endregion
//
//#region Actions ...
//
//#region Global ...
/**
* retrieve a path status ...
*
* @param {string} path a path value to check ...
* @returns an stat object ...
*/
function getStatus(path = '') {
//
if (!XValueTools.isValidArg(path)) {
return undefined;
}
//
return fs.statSync(path);
}
/**
* retrieve user's Home path ...
*
* @returns {string} a path ...
*/
function getHomePath() {
return os.homedir();
}
//#endregion
//
//#region Path ...
/**
* retrieve the base name of specific address path ...
*
* @param {string} path address of file or folder ...
* @returns string ...
*/
function basename(path = '') {
//
if (!XValueTools.isValidArg(path)) {
return '';
}
//
const result = Path.basename(path);
return result;
}
/**
* join several path segments together ...
*
* @param {...string} path path params ...
* @returns a joined paths ...
*/
function joinPath(...path) {
return Path.join(...path);
}
/**
* resolve a relative path to absolute ...
*
* @param {string[]} path a path value to check ...
* @returns {string}
*/
function resolvePath(...path) {
return Path.resolve(...path);
}
//#endregion
//
//#region File ...
/**
* determines a path destination is a file or not ...
*
* @param {string} path a path value to check ...
* @returns a boolean value ...
*/
function isFileExists(path = '') {
//
if (!XValueTools.isValidArg(path)) {
return false;
}
//
try {
const stat = getStatus(path);
if (!stat) {
return false;
}
//
return stat.isFile();
} catch {
return false;
}
}
/**
* remove a file ...
*
* @param {string} path a file path ...
* @returns {Promise<boolean>} action done or not ...
*/
function removeFile(path = '') {
return new Promise((resolve) => {
//
if (!isFileExists(path)) {
resolve(false);
}
//
fs.unlink(path, (err) => {
//
if (err) {
resolve(false);
return;
}
//
resolve(true);
});
});
}
/**
* copy a file to destination path ...
*
* @param {string} source source file path ...
* @param {string} dest dest folder path ...
* @returns {Promise<boolean>} action done or not ...
*/
function copyFile(
source = '',
dest = ''
) {
return new Promise((resolve) => {
//
if (
!isFileExists(source) ||
!isDirectoryExists(dest)
) {
resolve(false);
return;
}
//
const destFilePath = Path.join(dest, Path.basename(source));
fs.copyFile(source, destFilePath, (err) => {
//
if (err) {
resolve(false);
return;
}
//
resolve(true);
});
});
}
/**
* reading specified file content ...
*
* @param {string} path a file path ...
* @returns {Promise<string>} file content ...
*/
function readFile(path = '') {
return new Promise((resolve) => {
//
if (!isFileExists(path)) {
resolve('');
return;
}
//
fs.readFile(path, 'utf8', (err, content) => {
//
if (err) {
resolve(undefined);
return;
}
//
resolve(content);
});
});
}
/**
* write content to a file ...
*
* @param {string} path a file path ...
* @param {string} content the content which going to write to the file ...
* @param {bool} overwrite determines file overwrite if exists ...
* @returns {Promise<boolean>} action done or not ...
*/
function writeFile(
path = '',
content = '',
overwrite = true
) {
return new Promise((resolve) => {
//
if (isFileExists(path) && !overwrite) {
//
resolve(false);
return;
}
//
// Normalize Content ...
content = XValueTools.isValidArg(content) ?
content :
'';
//
fs.writeFile(path, content, (err) => {
//
if (err) {
//
resolve(false);
return;
}
//
resolve(true);
});
});
}
/**
* create a file ...
*
* @param {string} path file path ...
* @param {string} fileName file name ...
* @returns {Promise<boolean>} action done or not ...
*/
function createFile(
path = '',
fileName = ''
) {
return new Promise((resolve) => {
//
const filePath = Path.join(path, fileName);
if (
isFileExists(filePath) ||
!XValueTools.isValidArg(path) ||
!XValueTools.isValidArg(fileName)
) {
//
resolve(false);
return;
}
//
fs.writeFile(filePath, '', (err) => {
//
if (err) {
//
resolve(false);
return;
}
//
resolve(true);
});
});
}
/**
* remove a file name extension ...
*
* @param {string} name
* @returns {string} name without extension ...
*/
function removeFileExtension(name = '') {
return name.substring(0, name.lastIndexOf('.')) || name;
}
/**
* retrieve a file extension ...
*
* @param {string} path a path which locate a file ...
* @returns {string}
*/
function getFileExtension(path = '') {
//
let result = "";
//
// Validate Arg ...
if (
!XValueTools.isValidArg(path)
|| !isFileExists(path)
) {
return result;
}
//
// Retrieve just file name ...
const fileName = basename(path);
result = fileName.replace(
removeFileExtension(fileName),
""
);
//
return result;
}
/**
* retrieve all files list recursively from specific path ...
*
* @param {string} path a source folder path ...
* @param {string[]} extensions which file extensions need to be listed, live empty for all files ...
* @returns {Promise<string[]>}
*/
async function getRecursiveFilesList(
path = "",
extensions = []
) {
//
let result = [];
//
// Validate Args ...
if (
!XValueTools.isValidArg(path)
|| !isDirectoryExists(path)
) {
return result;
}
//
const contents = await getDirectoryContents(path);
for (const item of contents) {
//
const itemPath = joinPath(
path,
item
);
//
const isItemFile = isFileExists(itemPath);
if (isItemFile) {
//
const itemFileExtension = getFileExtension(itemPath);
const isFileInSupportedExtensions =
extensions === undefined || extensions.length === 0
? true
: extensions.includes(itemFileExtension)
;
if (isFileInSupportedExtensions) {
result.push(itemPath);
}
} else if (isDirectoryExists(itemPath)) {
//
const itemPathFiles = await getRecursiveFilesList(itemPath, extensions);
result.push(...itemPathFiles);
}
}
//
return result;
}
/**
* Extract Specific files from a folder and it's content ...
*
* @param {string} path Folder Path ...
* @returns
*/
async function extractFiles(path = "", ext = [], excludeWorkspaceFolders = []) {
//
const result = [];
//
if (!ext || ext.length == 0) {
return result;
}
//
const pathContent = await getDirectoryContents(path);
if (!pathContent || pathContent.length == 0) {
return result;
}
//
// Loop through Content ...
for (const c of pathContent) {
//
// Prepare full path ...
const cPath = joinPath(path, c);
//
// check content path is file or not ...
const isCFile = isFileExists(cPath);
const isCDirectory = isDirectoryExists(cPath);
if (isCFile) {
//
// Check it is MQL file or not ...
const cExt = getFileExtension(cPath);
if (ext.includes(cExt)) {
result.push(cPath);
}
} else if (isCDirectory) {
//
const destFolderName = basename(cPath);
const isExcluded = excludeWorkspaceFolders.includes(destFolderName);
if (isExcluded) {
continue;
}
//
const cFiles = await extractFiles(cPath, ext);
if (cFiles && cFiles.length > 0) {
result.push(...cFiles);
}
}
}
//
return result;
}
//#endregion
//
//#region Directory ...
/**
* create a directory ...
*
* @param {string} path destination path including dir name ...
* @param {boolean} recursive create directories recursively ...
* @returns action done or not ...
*/
function createDirectory(
path = '',
recursive = true
) {
//
let result = false;
//
if (
isDirectoryExists(path) ||
!XValueTools.isValidArg(path)
) {
return false;
}
//
try {
//
fs.mkdirSync(path, { recursive: recursive });
result = true;
return result;
} catch {
return false;
}
}
/**
* remove a directory ...
*
* @param {string} path destination path including dir name ...
* @param {boolean} recursive removes directories recursively ...
* @returns {Promise<boolean>} action done or not ...
*/
function removeDirectory(
path = '',
recursive = false
) {
return new Promise((resolve) => {
//
if (!isDirectoryExists(path)) {
resolve(false);
return;
}
//
fs.rm(path, {
recursive
}, (err) => {
//
if (err) {
resolve(false);
return;
}
//
resolve(true);
});
});
}
/**
* determines a path destination is a directory or not ...
*
* @param {string} path a folder path ...
* @returns represent destnation path is Directory or not ...
*/
function isDirectoryExists(path = '') {
//
if (!XValueTools.isValidArg(path)) {
return false;
}
//
try {
//
const isExists = fs.existsSync(path);
if (!isExists) {
return false;
}
//
const stat = getStatus(path);
if (!stat) {
return false;
}
//
const result = stat.isDirectory();
return result;
} catch {
return false;
}
}
/**
* retrieve a directory content ...
*
* @param {string} path a folder path ...
* @returns {Promise<string[]>} a collection of folder files ...
*/
function getDirectoryContents(path = '') {
return new Promise((resolve) => {
//
if (!isDirectoryExists(path)) {
resolve([]);
return;
}
//
fs.readdir(path, (err, content) => {
//
if (err) {
resolve([]);
return;
}
//
resolve(content);
});
});
}
/**
* retrieve a directory files ...
*
* @param {string} path a folder path ...
* @returns {Promise<string[]>} a collection of folder files ...
*/
function getDirectoryFiles(
path = '',
containsHiddenFiles = false
) {
return new Promise((resolve) => {
//
if (!isDirectoryExists(path)) {
resolve([]);
return;
}
//
fs.readdir(path, (err, content) => {
//
if (err) {
resolve([]);
return;
}
//
if (!containsHiddenFiles) {
content = content.filter(c => !c.startsWith('.'));
}
//
const result = [];
content
.forEach(c => {
//
const cPath = Path.join(path, c);
if (isFileExists(cPath)) {
result.push(c);
}
});
//
resolve(result);
});
});
}
/**
* retrieve a directory folders ...
*
* @param {string} path a folder path ...
* @returns {Promise<string[]>} a collection of folder names ...
*/
function getDirectoryFolders(path = '') {
return new Promise((resolve) => {
//
if (!isDirectoryExists(path)) {
resolve([]);
return;
}
//
fs.readdir(path, (err, content) => {
//
if (err) {
resolve([]);
return;
}
//
const result = [];
content.forEach(c => {
//
const cPath = Path.join(path, c);
if (isDirectoryExists(cPath)) {
result.push(c);
}
});
//
resolve(result);
});
});
}
/**
* copy a folder with all of it's content to dest ...
*
* @param {string} source source folder path ...
* @param {string} dest dest folder path ...
* @returns {Promise<boolean>} action done or not ...
*/
async function copyFolder(
source = '',
dest = ''
) {
//
if (
!isDirectoryExists(source) ||
!XValueTools.isValidArg(dest) ||
!XValueTools.isValidArg(source)
) {
return false;
}
//
const folderName = Path.basename(source);
const destPath = Path.join(dest, folderName);
//
// Create Dest Path folder if not exists ...
if (!isDirectoryExists(destPath)) {
//
let result = createDirectory(destPath, true);
if (!result) {
return false;
}
}
//
// Files ...
const files = await getDirectoryFiles(source);
if (files && files.constructor === Array && files.length > 0) {
//
const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath));
const filesResult = (await Promise.all(filesPromises)).every(r => !!r);
if (!filesResult) {
return false;
}
}
//
// Folders ...
const folders = await getDirectoryFolders(source);
if (folders && folders.constructor === Array && folders.length > 0) {
//
const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath));
const filesResult = (await Promise.all(folderPromises)).every(r => !!r);
if (!filesResult) {
return false;
}
}
//
return true;
}
//#endregion
//
//#region Downloader ...
/**
* download a file from specific url and store it ...
*
* @param {string} filepath the file name and path which required to put download file on it ...
* @param {string} url the web url for downloading ...
*/
function download(filepath, url) {
//
// Validate Args ...
if (
!XValueTools.isValidArg(url)
|| !XValueTools.isValidURL(url)
|| !XValueTools.isValidArg(filepath)
) {
return;
}
//
var file = fs.createWriteStream(filepath);
//
if (url.startsWith('https:')) {
https.get(url, function (response) {
response.pipe(file);
});
} else if (url.startsWith('http:')) {
http.get(url, function (response) {
response.pipe(file);
});
}
}
//#endregion
//
//#region JSON ...
/**
* read and parse a JSON content from a file ...
*
* @param {string} path source file path ...
* @returns {any}
*/
function readJSON(path = "") {
//
// Validate Args ...
if (!isFileExists(path)) {
return undefined;
}
//
let result = undefined;
try {
result = require(path);
} catch {
result = undefined;
}
//
return result;
}
/**
* write a JSON Object content into a file ...
*
* @param {string} path dest file path ...
* @param {any} content an object which required to write to file ...
* @returns {Promise<boolean>}
*/
async function writeJSON(
path = "",
content = undefined
) {
//
let result = false;
//
// Validate Args ...
if (!XValueTools.isValidArg(path)) {
return result;
}
//
// Normallize Content ...
if (content === undefined) {
content = {};
}
//
const contentString = XValueTools.beautifyJSON(content);
//
result = await writeFile(
path,
contentString,
true
);
//
return result;
}
//#endregion
//#endregion
//
//#region Module Exports ...
module.exports = {
//
CurrentDir,
PathSeparator,
//
getStatus,
getHomePath,
//
basename,
joinPath,
resolvePath,
//
download,
//
readJSON,
writeJSON,
//
copyFile,
readFile,
writeFile,
createFile,
removeFile,
isFileExists,
getFileExtension,
removeFileExtension,
getRecursiveFilesList,
extractFiles,
//
copyFolder,
createDirectory,
removeDirectory,
createDirectory,
removeDirectory,
isDirectoryExists,
isDirectoryExists,
getDirectoryFiles,
getDirectoryFolders,
getDirectoryContents,
};
//#endregion
+219
View File
@@ -0,0 +1,219 @@
/**
* XShell Tools Module ...
* a module for handling shell actions and retrieve OS Info in node js ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
//#region Imports ...
const os = require('os');
const process = require('process');
const { exec } = require("child_process");
const XFileTools = require('./x-file.tools');
//#endregion
//
//#region Constants ...
//
const OS = {
Aix: 'aix',
Darwin: 'darwin',
FreeBSD: 'freebsd',
Linux: 'linux',
OpenBSD: 'openbsd',
SnOS: 'sunos',
Windows: 'win32'
};
//
const isWindows = process.platform === OS.Windows;
//#endregion
//
//#region Actions ...
//
//#region Pure shell commands ...
/**
* execute a command using NodeJS on shell ...
*
* @param {string} cmd command to execute ...
* @param {string} cwd working directory ...
*
* @returns Promise<any, errr> instance ...
*/
function execute(cmd, cwd) {
return new Promise((resolve, reject) => {
//
if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) {
reject('invalid args ...');
return;
}
//
exec(cmd, { cwd }, (err, result, stdError) => {
//
if (err) {
reject(err);
return;
}
//
if (stdError) {
//
// reject(stdError);
// return;
}
//
resolve(result);
});
});
};
/**
* determines a command exists on host or not ...
*
* @param {string} name specific command name ...
*
* @returns boolean Promise ...
*/
function checkCommandExists(name) {
return new Promise(resolve => {
//
if (!name) {
resolve(false);
return;
}
//
const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`;
execute(cmd).then(result => {
resolve(true);
})
.catch(err => {
resolve(false);
});
});
}
//#endregion
//
//#region required commands state ...
/**
* check al required commands exists or not ...
*
* @returns
*/
async function isRequiredCommandsExists() {
//
let result = false;
//
// const isTarExists = await isTarCommandExists();
// const isCatExists = await isCatCommandExists();
// const isGrepExists = await isGrepCommandExists();
// const isSedExists = await isSedCommandExists();
const isNpmExists = await isNpmCommandExists();
const isNgExists = await isNgCommandExists();
const isIonicExists = await isIonicCommandExists();
const isCordovaExists = await isCordovaCommandExists();
//
result = isNpmExists
&& isNgExists
&& isIonicExists
&& isCordovaExists
;
//
return result;
}
/**
* retrieve required commands state object ...
*
* @returns
*/
async function getRequiredCommandsStates() {
//
const result = {};
//
// const isTarExists = await isTarCommandExists();
// const isCatExists = await isCatCommandExists();
// const isGrepExists = await isGrepCommandExists();
// const isSedExists = await isSedCommandExists();
const isNpmExists = await isNpmCommandExists();
const isNgExists = await isNgCommandExists();
const isIonicExists = await isIonicCommandExists();
const isCordovaExists = await isCordovaCommandExists();
//
result['npm'] = isNpmExists;
result['ng'] = isNgExists;
result['ionic'] = isIonicExists;
result['cordova'] = isCordovaExists;
//
return result;
}
//#endregion
//
//#region Commonly used Command Checkers ...
/**
* determines npm command exists or not ...
*
* @returns
*/
function isNpmCommandExists() {
return checkCommandExists('npm');
}
/**
* determines ng command exists or not ...
*
* @returns
*/
function isNgCommandExists() {
return checkCommandExists('ng');
}
/**
* determines ionic command exists or not ...
*
* @returns
*/
function isIonicCommandExists() {
return checkCommandExists('ionic');
}
/**
* determines cordova command exists or not ...
*
* @returns
*/
function isCordovaCommandExists() {
return checkCommandExists('cordova');
}
//#endregion
//#endregion
//
//#region Module Exports ...
module.exports = {
//
execute,
checkCommandExists,
isRequiredCommandsExists,
getRequiredCommandsStates,
//
isNgCommandExists,
isIonicCommandExists,
isCordovaCommandExists,
}
//#endregion
@@ -0,0 +1,268 @@
/**
* DataType Tools Module ...
* a module for manipulate and detect supported data types in node js ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
//#region Constants ...
/**
* all supported data types ...
*/
const DataTypes = {
Null: 'null',
Date: 'date',
Array: 'array',
Object: 'object',
String: 'string',
Number: 'number',
Unknown: 'unknown',
Boolean: 'boolean',
Function: 'function',
Undefined: 'undefined',
};
//#endregion
//
//#region Actions ...
/**
* detect type of a content ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function getType(value) {
//
const type = typeof value;
//
let result = DataTypes.Unknown;
let dateIdentifier = '[object Date]';
let constructor = value && value.constructor ?
value.constructor.toString() :
'';
//
switch (type) {
//
case 'undefined':
result = DataTypes.Undefined;
break;
//
case 'boolean':
result = DataTypes.Boolean;
break;
//
case 'string':
result = DataTypes.String;
break;
//
case 'number':
result = DataTypes.Number;
break;
//
case 'function':
result = DataTypes.Function;
break;
//
case 'object':
//
// Null ...
if (value === null) {
result = DataTypes.Null;
} else
//
// Array ...
if (Array.isArray(value)) {
result = DataTypes.Array;
} else
//
// Data ...
if (
value instanceof Date ||
isFunction(value.getMonth) ||
constructor.includes(dateIdentifier) ||
Object.prototype.toString.call(value) === dateIdentifier
) {
result = DataTypes.Date;
} else
//
// Object ...
{
result = DataTypes.Object;
}
break;
//
default:
result = DataTypes.Unknown;
break;
}
//
return result;
}
/**
* retrieve an object constructor ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function getConstructor(value) {
//
const result = value && value.constructor ?
value.constructor.toString() :
'';
//
return result;
}
/**
* retrieve an object prototype ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function getPrototype(value) {
//
const result = value ?
Object.prototype.toString.call(value) :
'';
//
return result;
}
/**
* check an object is null or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isNull(value) {
return getType(value) === DataTypes.Null;
}
/**
* check an object is undefined or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isUndefined(value) {
return getType(value) === DataTypes.Undefined;
}
/**
* check an object is null or undefined or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isNullOrUndefined(value) {
return isNull(value) || isUndefined(value);
}
/**
* check an object is a date or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isDate(value) {
return getType(value) === DataTypes.Date;
}
/**
* check an object is number or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isNumber(value) {
return getType(value) === DataTypes.Number;
}
/**
* check an object is string or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isString(value) {
return getType(value) === DataTypes.String;
}
/**
* check an object is boolean or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isBoolean(value) {
return getType(value) === DataTypes.Boolean;
}
/**
* check an object is an Array or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isArray(value) {
return getType(value) === DataTypes.Array;
}
/**
* check an object is and Object or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isObject(value) {
return getType(value) === DataTypes.Object;
}
/**
* check an object is a Function or not ...
*
* @param {any} value the content which going to check ...
* @returns
*/
function isFunction(value) {
return getType(value) === DataTypes.Function;
}
//#endregion
//
//#region Module Exports ...
module.exports = {
//
DataTypes,
//
getType,
getConstructor,
getPrototype,
isNull,
isUndefined,
isNullOrUndefined,
isDate,
isNumber,
isString,
isBoolean,
isArray,
isObject,
isFunction,
}
//#endregion
File diff suppressed because it is too large Load Diff
+702
View File
@@ -0,0 +1,702 @@
///////////////////////////////////////////////////////
//
// SaherElm IT Center XTest MQL5 Expert Advisor
// -------------------------------------------------
// Name: XSTestEA
// Description: an Exper Advisor which used XTestSetup
// to Analyse Market ...
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////x
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XSTestEA"
#property strict
//
#define ShortName "XSTestEA"
//
// Imports ...
#include "../Helpers/x-saherelm.xct.helper.mq5"
#include "../Helpers/x-saherelm.xcc.helper.mq5"
//
#include "../Parsers/x-saherelm.xch.parser.mq5"
#include "../Strategies/x-saherelm.xch.strategy.mq5"
//
// Inputs ...
//
// Common ...
input group "Common";
input long eaMagicNumber = 78692110; // Magic Number
input int eaSlippage = 10; // Slippgae
input string eaLogSuffix = ""; // Log Suffix
//
// Symbols ...
input group "Symbols";
input bool eaMultiSymbol = false; // Use Multi Symbol
input bool eaUseMaxAllowedTradesPerSymbol = true; // Use Max Allowed Trades Per Symbol
input string eaSymbols = "EURUSDb,USDJPYb"; // Trading Symbols
// string eaSymbols = "EURUSDb,USDJPYb,USDCHFb,GBPUSDb,XAUUSDb,XAGUSDb"; // Trading Symbols
//
// Trades ...
input group "Trades";
input double eaVolume = 0.01; // Static Volume
input double eaR2R = 1.5; // Risk to Reward Ratio for Dynamic TP SL
input bool eaUseFixedTPSLPoints = true; // Use Fixed TP SL in Points
input bool eaIgnoreTP = false; // Ignore TP
input bool eaIgnoreSL = false; // Ignore SL
input double eaTPPoint = 150; // Static TP Point
input double eaSLPoint = 500; // Static SL Point
//
// Risk Management ...
input group "Risk Management";
//
// Risk Management > Trade Management ...
input group "Trade Management";
input double eaAllowLong = true; // Allow Long Positions
input double eaAllowShort = true; // Allow Short Positions
input int eaMaxAllowedLongs = 1; // Max Allowed Long Positions
input int eaMaxAllowedShorts = 1; // Max Allowed Short Positions
input double eaMaxDrawdownPercentForOpenTrades = 3; // Max Drawdown Percent for Open Trades
//
// Risk Management > Hedging ...
input group "Hedging";
input bool eaAllowHedging = true; // Allow Hedging Trades
input int eaMinTradesForHedge = 2; // Minimum Open Trades for Hedging
input double eaMinimumProfitPerVolumeForHedging = 0.3; // Minimum Required Profit per Volume for Hedging
//
// Risk Management > Trailling Stop ...
input group "Trailling Stop";
input bool eaAllowTrailStop = false; // Allow Trail Stop
input double eaStartTrailInPoint = 100; // Trail Start After Profit (Point)
input double eaTrailStepInPoint = 30; // Trail Size in each Step (Point)
input bool eaIgnoreTPAfterTrail = true; // Ignore TP after Trail
//
// Risk Management > Trades Recovery ...
input group "Trades Recovery";
input bool eaAllowRecovery = false; // Allow Recover Trades
input double eaRecoveryTPPoint = 150; // Recovery TP (Point)
input double eaRecoverySLPoint = 200; // Recovery SL (Point)
input int eaMaxAllowedRecoveryTrades = 0; // Max Allowed Recovery Trades
input double eaRecoveryVolumeMultiplier = 2; // Recovery Volume Multiplier
input double eaMaxAllowedRecoveryTradesVolume = 0.1; // Max Allowed Recovery Volume
//
// Alert ...
input group "Alert";
input bool eAEnableAlerts = true; // Enable Alerts
input bool eALogAlerts = true; // Log Alerts
input bool eAMailAlerts = false; // Mail Alerts
input bool eAPushAlerts = false; // Push Alerts
input bool eATerminalAlerts = false; // Terminal Alerts
//
// Time Report ...
input group "Reports";
input bool eaAlertNewMonths = false; // Alert New Month
input bool eaAlertNewWeeks = false; // Alert New Weeks
input bool eaAlertNewDays = false; // Alert New Days
input bool eaAlertNewHours = false; // Alert New Hours
//
// Variables ...
//
// int mNumberOfSLs = 0;
//
// Bar Style nad Time Instances ...
XSCXCTHelper *mCTHelper;
XSCXCCHelper *mCCHelper;
//
// Registred Strategies ...
XSCBaseStrategy *strategies[];
//
// Trader Instance Class ...
XSCTrade *eaTrader;
//
// Alert Class ...
XSCAlert *eaAlert;
//
// Time Tracker ...
XTimeTracker eaTimeTracker;
//
// Trade Handler Instance Class ...
XSCXTradeHandler *eaTradeHandler;
//
string mTag =
!IsValid(eaLogSuffix)
? ShortName
: ShortName + "_" + eaLogSuffix;
//
// Event Handlers ...
//
// Initialization ...
int OnInit()
{
//
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
if (!InitialEA())
{
return INIT_FAILED;
}
//
drawPrefix = mTag;
//
// EventSetTimer(1);
// EventSetMillisecondTimer(100);
//
// Init Succeed ...
return INIT_SUCCEEDED;
}
//
// DeInitialization ...
void OnDeinit(const int reason)
{
//
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
// REASON_REMOVE 1 Program removed from a chart
// REASON_RECOMPILE 2 Program recompiled
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
// REASON_CHARTCLOSE 4 Chart closed
// REASON_PARAMETERS 5 Inputs changed by a user
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
// REASON_TEMPLATE 7 Another chart template applied
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
// REASON_CLOSE 9 Terminal closed
//
string msg = "MaxSameTimeTrades: " + ToString(eaTradeHandler.MaxSameTimeTrades());
eaAlert.Alert(msg);
//
// De Initialize XSampleEA Providers ...
delete mCTHelper;
delete mCCHelper;
//
delete eaAlert;
delete eaTrader;
delete eaTradeHandler;
//
// EventKillTimer();
//
Clean(strategies);
}
//
// On Tick Handler ...
void OnTick()
{
//
HandleTradeState();
HandleTimeReport();
HandleStrategiesOnTick();
}
//
// Handle On Trade Event ...
void OnTrade()
{
eaTrader.HandleOnTrade();
}
//
// On Timer ...
void OnTimer()
{
//
// HandleTradeState();
// HandleTimeReport();
// HandleStrategiesOnTick();
// //
// if (eaTimeTracker.IsNewDay())
// {
// mNumberOfSLs = 0;
// }
}
//
// Custom Functions ...
//
// Validate Inputs ...
bool ValidateInputs()
{
//
bool result = false;
//
result = true;
//
return result;
}
//
// Initialize all Requirements ...
bool InitialEA()
{
//
bool result = false;
//
// Bar Timer ...
XCTInputs ctInputs;
ctInputs.Default();
mCTHelper = new XSCXCTHelper();
result = mCTHelper.Init(
_Symbol,
_Period,
ctInputs //
);
if (!result)
{
return result;
}
//
// Bar Styles ...
XCCInputs ccInputs;
ccInputs.Default();
mCCHelper = new XSCXCCHelper();
result = mCCHelper.Init(
_Symbol,
_Period,
ccInputs //
);
if (!result)
{
return result;
}
//
// Create Instance of Alert Class ...
eaAlert = new XSCAlert();
eaAlert.SetPrefix(mTag);
eaAlert.SetLogAlerts(eALogAlerts);
eaAlert.SetMailAlerts(eAMailAlerts);
eaAlert.SetPushAlerts(eAPushAlerts);
eaAlert.SetEnableAlerts(eAEnableAlerts);
eaAlert.SetTerminalAlerts(eATerminalAlerts);
//
// Create Trader Instance ...
eaTrader = new XSCTrade(
eaSlippage,
eaMagicNumber //
);
eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered);
eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
//
// Initialize Trade Handler ...
eaTradeHandler = new XSCXTradeHandler(eaTrader);
eaTradeHandler.SaveTrades(true);
eaTradeHandler.SaveSignals(true);
//
// Configure Alerts ...
eaTradeHandler.SetAlertPrefix(mTag);
eaTradeHandler.SetAlertEnableAlerts(eAEnableAlerts);
eaTradeHandler.SetAlertLogAlerts(eALogAlerts);
eaTradeHandler.SetAlertMailAlerts(eAMailAlerts);
eaTradeHandler.SetAlertPushAlerts(eAPushAlerts);
eaTradeHandler.SetAlertTerminalAlerts(eATerminalAlerts);
//
// Configure Trade Management ...
eaTradeHandler.AllowLong(eaAllowLong);
eaTradeHandler.AllowShort(eaAllowShort);
eaTradeHandler.MaxAllowedLongs(eaMaxAllowedLongs);
eaTradeHandler.MaxAllowedShorts(eaMaxAllowedShorts);
eaTradeHandler.UseMaxAllowedTradesPerSymbol(eaUseMaxAllowedTradesPerSymbol);
eaTradeHandler.MaxDrawdownPercentForOpenTrades(eaMaxDrawdownPercentForOpenTrades);
//
// Configure Hedging ...
eaTradeHandler.AllowHedging(eaAllowHedging);
eaTradeHandler.HedgeVolumeFactor(eaVolume);
eaTradeHandler.MinTradesForHedge(eaMinTradesForHedge);
eaTradeHandler.HedgeMinProfitPerVolumeFactor(eaMinimumProfitPerVolumeForHedging);
//
// Configure Trailing ...
eaTradeHandler.AllowTrailStops(eaAllowTrailStop);
eaTradeHandler.TrailBasedOnProfit(true);
eaTradeHandler.TrailStartInPoint(eaStartTrailInPoint);
eaTradeHandler.TrailStepInPoint(eaTrailStepInPoint);
eaTradeHandler.IgnoreTPOnTrail(eaIgnoreTPAfterTrail);
//
// Configure Recovery ...
eaTradeHandler.AllowRecover(eaAllowRecovery);
eaTradeHandler.ForcePressuresInRecovery(false);
eaTradeHandler.RecoveryTPPoint(eaRecoveryTPPoint);
eaTradeHandler.RecoverySLPoint(eaRecoverySLPoint);
eaTradeHandler.MaxAllowedRecover(eaMaxAllowedRecoveryTrades);
eaTradeHandler.RecoveryVolumeMultiplier(eaRecoveryVolumeMultiplier);
eaTradeHandler.MaxAllowedRecoveryVolume(eaMaxAllowedRecoveryTradesVolume);
//
// Single Symbol ...
if (!eaMultiSymbol)
{
//
// Create Class Instance ...
XSCXCHStrategy *xchStrategy;
xchStrategy = new XSCXCHStrategy(
_Symbol,
_Period,
PERIOD_H1, // Analyzing Period
eaVolume,
eaR2R, // R2R ...
eaSlippage,
eaMagicNumber,
true, // Ignore Signal Execution
eaUseFixedTPSLPoints, // Use TP SL Point
false, // Use Max
eaTPPoint, // TP
eaSLPoint, // SL
eaIgnoreTP,
eaIgnoreSL,
eaAllowLong,
eaAllowShort,
eaMaxAllowedLongs, // Max Longs
eaMaxAllowedShorts // Max Shorts
);
//
// Configuere Strategy ...
xchStrategy.EnableXCHM(true);
xchStrategy.EnableXCHHK(true);
xchStrategy.EnableXCHSTR(true);
xchStrategy.EnableXCHCHE(true);
xchStrategy.DrawImportantAreas(false);
xchStrategy.AddXCHSignalEventHandler(OnSignalRecieved);
//
// Configure Alerts ...
xchStrategy.SetAlertPrefix(mTag);
xchStrategy.SetAlertEnableAlerts(eAEnableAlerts);
xchStrategy.SetAlertLogAlerts(eALogAlerts);
xchStrategy.SetAlertMailAlerts(eAMailAlerts);
xchStrategy.SetAlertPushAlerts(eAPushAlerts);
xchStrategy.SetAlertTerminalAlerts(eATerminalAlerts);
//
// Register Strategy ...
RegisterStrategy(xchStrategy);
}
//
// Multi Symbol ...
else
{
//
// Parse Symbols ...
string symbols[];
int symbolsCount = SplitContent(
symbols,
eaSymbols //
);
result = IsValidSize(symbolsCount);
if (!result)
{
return result;
}
//
for (int i = 0; i < symbolsCount; i++)
{
//
// Select Symbol ...
string iSymbol = symbols[i];
//
// Create Class Instance ...
XSCXCHStrategy *iStrategy;
iStrategy = new XSCXCHStrategy(
iSymbol,
_Period,
PERIOD_H1, // Analyzing Period
eaVolume,
eaR2R, // R2R ...
eaSlippage,
eaMagicNumber,
true, // Ignore Signal Execution
true, // Use TP SL Point
false, // Use Max
eaTPPoint, // TP
eaSLPoint, // SL
eaIgnoreTP,
eaIgnoreSL,
eaAllowLong,
eaAllowShort,
eaMaxAllowedLongs, // Max Longs
eaMaxAllowedShorts // Max Shorts
);
//
// Configuere Strategy ...
iStrategy.EnableXCHM(true);
iStrategy.EnableXCHHK(true);
iStrategy.EnableXCHSTR(true);
iStrategy.EnableXCHCHE(true);
iStrategy.DrawImportantAreas(false);
iStrategy.AddXCHSignalEventHandler(OnSignalRecieved);
//
// Configure Alerts ...
iStrategy.SetAlertPrefix(mTag);
iStrategy.SetAlertEnableAlerts(eAEnableAlerts);
iStrategy.SetAlertLogAlerts(eALogAlerts);
iStrategy.SetAlertMailAlerts(eAMailAlerts);
iStrategy.SetAlertPushAlerts(eAPushAlerts);
iStrategy.SetAlertTerminalAlerts(eATerminalAlerts);
//
// Register Strategy ...
RegisterStrategy(iStrategy);
}
}
//
return result;
}
//
// Register Strategy ...
void RegisterStrategy(XSCBaseStrategy *strategy)
{
//
if (strategy == NULL)
{
return;
}
//
ArrayResize(
strategies,
ArraySize(strategies) + 1 //
);
//
strategies[ArraySize(strategies) - 1] = strategy;
}
//
// Call All Registered Strategis Tick Handler Functions ...
void HandleStrategiesOnTick()
{
//
int count = ArraySize(strategies);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
// Call Tick Handler Function ...
strategies[i].HandleTick();
}
}
//
// Manage Trading States ...
void HandleTradeState()
{
//
// Implement All Trade States here ...
eaTradeHandler.UpdateData();
//
// Do Protection Senarios ...
eaTradeHandler.HandleProtection();
}
//
// Time Reporting ...
void HandleTimeReport()
{
//
// Monthly Report ....
if (eaAlertNewMonths &&
eaTimeTracker.IsNewMonth())
{
//
string msg = "New Month ...";
//
eaAlert.Alert(msg);
}
//
// Weekly Report ....
if (eaAlertNewWeeks &&
eaTimeTracker.IsNewWeek())
{
//
string msg = "New Week ...";
//
eaAlert.Alert(msg);
}
//
// Daily Report ....
if (eaAlertNewDays &&
eaTimeTracker.IsNewDay())
{
//
string msg = "New Day ...";
//
eaAlert.Alert(msg);
}
//
// Hourly Report ....
if (eaAlertNewHours &&
eaTimeTracker.IsNewHour())
{
//
string msg = "New Hour ...";
//
eaAlert.Alert(msg);
}
}
//
// SIGNAL EVENT Handlers ...
//
//
// All Signals from Strategies Comming Here for Execution or
// Analyzing ...
void OnSignalRecieved(
XSignal &signal,
XCHStrategyConditions &conditions //
)
{
//
// Check Signal and Conditions Validations ...
//
if (!signal.IsValid())
{
return;
}
//
if (!conditions.IsValid())
{
return;
}
//
XCHStartegyConditionsParser parser;
bool isFiltered = parser.IsFiltered(
signal,
conditions //
);
if (isFiltered)
{
return;
}
//
// Attach Conditions Summary to Signal ...
string conditionsSummary = conditions.GenerateSummary(
false,
false,
true,
false //
);
//
signal.conditions = parser.GenerateSignalConditions(conditions); // conditionsSummary;
//
// Execute Signal Using Trade Handler ...
ENUM_X_SIGNAL_EXECUTION_RESULT state;
bool isExecuted = eaTradeHandler.ExecuteSignal(
signal,
state //
);
}
//
void OnStopLossTriggered(const XDeal &deal)
{
//
// Finish ...
eaTradeHandler.Finish(deal);
}
//
void OnTakeProfitTriggered(const XDeal &deal)
{
//
// Finish ...
eaTradeHandler.Finish(deal);
}
//
void OnPositionForceClosed(
const ulong ticket,
const XPosition &position,
const string comment //
)
{
//
// Finish ...
eaTradeHandler.Finish(
ticket,
position,
comment //
);
}
//
-9
View File
@@ -108,9 +108,6 @@ bool eaAlertNewHours = false; // Alert New Hours
//
// Variables ...
//
// int mNumberOfSLs = 0;
//
// Bar Style nad Time Instances ...
XSCXCTHelper *mCTHelper;
@@ -235,12 +232,6 @@ void OnTimer()
// HandleTradeState();
// HandleTimeReport();
// HandleStrategiesOnTick();
// //
// if (eaTimeTracker.IsNewDay())
// {
// mNumberOfSLs = 0;
// }
}
//
File diff suppressed because it is too large Load Diff
+830
View File
@@ -0,0 +1,830 @@
///////////////////////////////////////////////////////
// SaherElm IT Center MQL5 Indicator
// -------------------------------------------
// Name: XCHVWAP
// Description: XCHVWAP Trend Detector ...
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XCHVWAP Indicator"
#property strict
//
#define ShortName "XCHVWAP"
//
// Includes Common Library ...
#include "../Libraries/x-saherelm.common.lib.mq5"
//
// Inputs ...
//
// Market ...
input group "Market";
input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To
//
input group "Cycles";
//
input group "Short";
input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period
input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period
//
input group "Medium";
input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period
input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period
//
input group "Long";
input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period
input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period
//
input group "Hind";
input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period
input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period
//
// Presentation ...
input group "Presentation";
input bool showShort = true; // Show Short Cycle Fast
input bool showMedium = true; // Show Medium Cycle Fast
input bool showLong = true; // Show Long Cycle Fast
input bool showHind = true; // Show Hind Cycle Fast
//
// Buffers ...
//
#property indicator_chart_window
//
#property indicator_buffers 14
#property indicator_plots 8
//
#define hideColorIDX 0
#define bullishColorIDX 1
#define bearishColorIDX 2
#define neuturalColorIDX 3
//
// Short ...
//
#define sBufferIndex 0
double sBuffer[];
//
#define sColorBufferIndex 1
double sColorBuffer[];
//
#define sPlotBufferIndex 0
#property indicator_label1 "XCHVWAP S"
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 CLR_NONE, clrGreen, clrRed, clrGray
#property indicator_style1 STYLE_DOT
#property indicator_width1 1
//
// Medium ...
//
#define mBufferIndex 2
double mBuffer[];
//
#define mColorBufferIndex 3
double mColorBuffer[];
//
#define mPlotBufferIndex 1
#property indicator_label2 "XCHVWAP M"
#property indicator_type2 DRAW_COLOR_LINE
#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray
#property indicator_style2 STYLE_DOT
#property indicator_width2 1
//
// Long ...
//
#define lBufferIndex 4
double lBuffer[];
//
#define lColorBufferIndex 5
double lColorBuffer[];
//
#define lPlotBufferIndex 2
#property indicator_label3 "XCHVWAP L"
#property indicator_type3 DRAW_COLOR_LINE
#property indicator_color3 CLR_NONE, clrGreen, clrRed, clrGray
#property indicator_style3 STYLE_DOT
#property indicator_width3 1
//
// Hind ...
//
#define hBufferIndex 6
double hBuffer[];
//
#define hColorBufferIndex 7
double hColorBuffer[];
//
#define hPlotBufferIndex 3
#property indicator_label4 "XCHVWAP H"
#property indicator_type4 DRAW_COLOR_LINE
#property indicator_color4 CLR_NONE, clrGreen, clrRed, clrGray
#property indicator_style4 STYLE_DOT
#property indicator_width4 1
//
// Data Buffers ...
//
// Volumes ...
#define volumeBufferIndex 8
double volumeBuffer[];
//
// Price ...
#define priceBufferIndex 9
double priceBuffer[];
//
// SHORT ...
#define sStateBufferIndex 10
double sStateBuffer[];
//
// MEDIUM ...
#define mStateBufferIndex 11
double mStateBuffer[];
//
// LONG ...
#define lStateBufferIndex 12
double lStateBuffer[];
//
// HIND ...
#define hStateBufferIndex 13
double hStateBuffer[];
//
// Variables ...
//
int maxLength;
//
// Short ...
int mSCycleLength = 0;
ENUM_TIMEFRAMES mSCPeriod = NULL;
//
// Medium ...
int mMCycleLength = 0;
ENUM_TIMEFRAMES mMCPeriod = NULL;
//
// Long ...
int mLCycleLength = 0;
ENUM_TIMEFRAMES mLCPeriod = NULL;
//
// Hind ...
int mHCycleLength = 0;
ENUM_TIMEFRAMES mHCPeriod = NULL;
//
// EVENT Handlers ...
//
// Initialization ...
int OnInit()
{
//
// Validate Inputs ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
if (!InitMarketCycles())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// because in some cases we may have more than one input for
// calculation and we must prevent any calculation
// untill we pass the biggest input length, here we get max Input length
// and then wait until pass it ...
maxLength = ExtractMaxLengthOfInputs();
//
// Define Index Buffers ...
DefineBuffers();
//
// Set Indicator ShortName ...
SetIndicatorName();
//
// Init Succeed ...
return INIT_SUCCEEDED;
}
//
// DeInitialization ...
void OnDeinit(const int reason)
{
//
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
// REASON_REMOVE 1 Program removed from a chart
// REASON_RECOMPILE 2 Program recompiled
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
// REASON_CHARTCLOSE 4 Chart closed
// REASON_PARAMETERS 5 Inputs changed by a user
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
// REASON_TEMPLATE 7 Another chart template applied
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
// REASON_CLOSE 9 Terminal closed
}
//
// Calculating what we want ...
int OnCalculate(
const int rates_total, // Total Bars on Chart ...
const int prev_calculated, // Total Calculated Bars on Charts ...
const datetime &time[], // History of Open Time ...
const double &open[], // History of Open Price ...
const double &high[], // History of High Price ...
const double &low[], // History of Low Price ...
const double &close[], // History of Close Price ...
const long &tick_volume[], // History of Tick Volumes on Bar ...
const long &volume[], // History of Trade Volumes ...
const int &spread[] // History of Spread Price ...
)
{
//
ArraySetAsSeries(low, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(tick_volume, true);
//
// this counts Available Bars ...
int limit;
//
limit =
(prev_calculated > rates_total || prev_calculated <= 0)
? rates_total
: (rates_total - prev_calculated) + 1;
//
// Main Loop ...
for (int i = limit - 1; i >= 0 && !IsStopped(); i--)
{
//
CalculateBuffers(
i,
prev_calculated,
rates_total,
//
open,
high,
close,
low,
tick_volume //
);
}
//
return rates_total;
}
//
// CUSTOM Functions ...
//
// Validate Input Args for Initialization ...
bool ValidateInputs()
{
//
bool result =
//
(IsValid(scMethod, scPeriod) &&
IsValid(mcMethod, mcPeriod) &&
IsValid(lcMethod, lcPeriod) &&
IsValid(hcMethod, hcPeriod))
//
;
//
return result;
}
//
// Initialize Market Cycles ...
bool InitMarketCycles()
{
//
bool result = false;
//
// Current Cycle Initialization ...
//
int cPeriodSeconds = PeriodSeconds(_Period);
//
// Short Cycle Initialization ...
//
// Find Cycle Period ...
if (scMethod == X_PERIOD_AUTO)
{
//
// Select Period ...
mSCPeriod = GetCyclePeriod(
X_MARKET_CYCLE_SHORT,
_Period //
);
}
else
{
mSCPeriod = scPeriod;
}
//
result = IsValid(mSCPeriod);
if (!result)
{
return result;
}
//
mSCycleLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds;
result = mSCycleLength > 0;
if (!result)
{
return result;
}
//
// Medium Cycle Initialization ...
//
// Find Cycle Period ...
if (mcMethod == X_PERIOD_AUTO)
{
//
// Select Period ...
mMCPeriod = GetCyclePeriod(
X_MARKET_CYCLE_MEDIUM,
_Period //
);
}
else
{
mMCPeriod = mcPeriod;
}
//
result = IsValid(mMCPeriod);
if (!result)
{
return result;
}
//
mMCycleLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds;
result = mMCycleLength > 0;
if (!result)
{
return result;
}
//
// Long Cycle Initialization ...
//
// Find Cycle Period ...
if (lcMethod == X_PERIOD_AUTO)
{
//
// Select Period ...
mLCPeriod = GetCyclePeriod(
X_MARKET_CYCLE_LONG,
_Period //
);
}
else
{
mLCPeriod = lcPeriod;
}
//
result = IsValid(mLCPeriod);
if (!result)
{
return result;
}
//
mLCycleLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds;
result = mLCycleLength > 0;
if (!result)
{
return result;
}
//
// Hind Cycle Initialization ...
//
// Find Cycle Period ...
if (hcMethod == X_PERIOD_AUTO)
{
//
// Select Period ...
mHCPeriod = GetCyclePeriod(
X_MARKET_CYCLE_HIND,
_Period //
);
}
else
{
mHCPeriod = hcPeriod;
}
//
result = IsValid(mHCPeriod);
if (!result)
{
return result;
}
//
mHCycleLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds;
result = mHCycleLength > 0;
if (!result)
{
return result;
}
//
return result;
}
//
// Set Indicator Short Name and also we can define Buffers Labels ...
void SetIndicatorName()
{
IndicatorSetString(INDICATOR_SHORTNAME, ShortName);
}
//
// Define Indexes and Styles ...
void DefineBuffers()
{
//
// Short ...
//
ArraySetAsSeries(sBuffer, true);
ArraySetAsSeries(sColorBuffer, true);
SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA);
SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX);
//
// Medium ...
//
ArraySetAsSeries(mBuffer, true);
ArraySetAsSeries(mColorBuffer, true);
SetIndexBuffer(mBufferIndex, mBuffer, INDICATOR_DATA);
SetIndexBuffer(mColorBufferIndex, mColorBuffer, INDICATOR_COLOR_INDEX);
//
// Long ...
//
ArraySetAsSeries(lBuffer, true);
ArraySetAsSeries(lColorBuffer, true);
SetIndexBuffer(lBufferIndex, lBuffer, INDICATOR_DATA);
SetIndexBuffer(lColorBufferIndex, lColorBuffer, INDICATOR_COLOR_INDEX);
//
// Hind ...
//
ArraySetAsSeries(hBuffer, true);
ArraySetAsSeries(hColorBuffer, true);
SetIndexBuffer(hBufferIndex, hBuffer, INDICATOR_DATA);
SetIndexBuffer(hColorBufferIndex, hColorBuffer, INDICATOR_COLOR_INDEX);
//
// Data Buffers ...
//
// Volumes ...
ArraySetAsSeries(volumeBuffer, true);
SetIndexBuffer(volumeBufferIndex, volumeBuffer, INDICATOR_CALCULATIONS);
//
// Price ...
ArraySetAsSeries(priceBuffer, true);
SetIndexBuffer(priceBufferIndex, priceBuffer, INDICATOR_CALCULATIONS);
//
// Short State ...
ArraySetAsSeries(sStateBuffer, true);
SetIndexBuffer(sStateBufferIndex, sStateBuffer, INDICATOR_CALCULATIONS);
//
// Medium State ...
ArraySetAsSeries(mStateBuffer, true);
SetIndexBuffer(mStateBufferIndex, mStateBuffer, INDICATOR_CALCULATIONS);
//
// Long State ...
ArraySetAsSeries(lStateBuffer, true);
SetIndexBuffer(lStateBufferIndex, lStateBuffer, INDICATOR_CALCULATIONS);
//
// Hind State ...
ArraySetAsSeries(hStateBuffer, true);
SetIndexBuffer(hStateBufferIndex, hStateBuffer, INDICATOR_CALCULATIONS);
}
//
// Retrieve all Exists Input Max Length ...
// use for Start Of Drawing ...
int ExtractMaxLengthOfInputs()
{
//
int result = 0;
//
result = MathMax(mSCycleLength, mMCycleLength);
result = MathMax(result, mLCycleLength);
result = MathMax(result, mHCycleLength);
//
return result;
}
//
// Calculate Buffers ...
void CalculateBuffers(
int bar_index, // Selected Bar Index
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[] //
)
{
//
// Calculate Volumes and Price ...
//
if (ratesTotal - bar_index <= maxLength)
{
//
CalculateDataBuffers(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume //
);
return;
}
//
CalculateDataBuffers(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume //
);
//
CalculateCycles(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume //
);
}
//
void CalculateDataBuffers(
int bar_index, // Selected Bar Index
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[] //
)
{
//
double price = GetAppliedPrice(
appliedTo,
open,
high,
low,
close,
bar_index //
);
priceBuffer[bar_index] = price;
volumeBuffer[bar_index] = (double)tickVolume[bar_index];
}
//
void CalculateCycles(
int bar_index, // Selected Bar Index
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[] //
)
{
//
// SHORT ...
CalculateCycle(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume,
//
mSCycleLength,
showShort,
sBuffer,
sColorBuffer,
sStateBuffer //
);
//
// MEDIUM ...
CalculateCycle(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume,
//
mMCycleLength,
showMedium,
mBuffer,
mColorBuffer,
mStateBuffer //
);
//
// LONG ...
CalculateCycle(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume,
//
mLCycleLength,
showLong,
lBuffer,
lColorBuffer,
lStateBuffer //
);
//
// HIND ...
CalculateCycle(
bar_index,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume,
//
mHCycleLength,
showHind,
hBuffer,
hColorBuffer,
hStateBuffer //
);
}
//
void CalculateCycle(
int bar_index, // Selected Bar Index
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[],
//
int _length, // Calculation Length
bool _show,
double &_buffer[],
double &_colorBuffer[],
double &_stateBuffer[] //
)
{
//
double vSum = 0;
double pSum = 0;
double mSum = 0;
for (int x = 0; x < _length; x++)
{
//
pSum += priceBuffer[x + bar_index];
vSum += volumeBuffer[x + bar_index];
mSum += priceBuffer[x + bar_index] * volumeBuffer[x + bar_index];
}
//
double iValue = mSum / vSum;
iValue = NormalizeDouble(iValue, _Digits);
//
_buffer[bar_index] = iValue;
//
bool isBullish = low[bar_index] > iValue;
bool isBearish = high[bar_index] < iValue;
//
double iColor =
isBullish
? bullishColorIDX
: isBearish
? bearishColorIDX
: neuturalColorIDX;
//
_colorBuffer[bar_index] = hideColorIDX;
_stateBuffer[bar_index] = iColor;
if (_show)
{
_colorBuffer[bar_index] = iColor;
}
}
//
+52
View File
@@ -653,6 +653,58 @@ struct XCHStartegyConditionsParser
(!conditions.chvlmConditions.isHSwitchedToBullish ? "!conditions.chvlmConditions.isHSwitchedToBullish &&" + "\n" : "") +
(!conditions.chvlmConditions.isHSwitchedToBearish ? "!conditions.chvlmConditions.isHSwitchedToBearish &&" + "\n" : "") +
"//" + "\n" +
"// XCHVWAP ..." + "\n" +
"//" + "\n" +
(conditions.chvwapConditions.hasBullishPower ? "conditions.chvwapConditions.hasBullishPower &&" + "\n" : "") +
(conditions.chvwapConditions.hasBearishPower ? "conditions.chvwapConditions.hasBearishPower &&" + "\n" : "") +
(conditions.chvwapConditions.isBullishPowerUp ? "conditions.chvwapConditions.isBullishPowerUp &&" + "\n" : "") +
(conditions.chvwapConditions.isBearishPowerUp ? "conditions.chvwapConditions.isBearishPowerUp &&" + "\n" : "") +
(conditions.chvwapConditions.isBullishPowerIncreasing ? "conditions.chvwapConditions.isBullishPowerIncreasing &&" + "\n" : "") +
(conditions.chvwapConditions.isBullishPowerDecreasing ? "conditions.chvwapConditions.isBullishPowerDecreasing &&" + "\n" : "") +
(conditions.chvwapConditions.isBearishPowerIncreasing ? "conditions.chvwapConditions.isBearishPowerIncreasing &&" + "\n" : "") +
(conditions.chvwapConditions.isBearishPowerDecreasing ? "conditions.chvwapConditions.isBearishPowerDecreasing &&" + "\n" : "") +
(conditions.chvwapConditions.isSBullish ? "conditions.chvwapConditions.isSBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isSBearish ? "conditions.chvwapConditions.isSBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isSSwitchedToBullish ? "conditions.chvwapConditions.isSSwitchedToBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isSSwitchedToBearish ? "conditions.chvwapConditions.isSSwitchedToBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isMBullish ? "conditions.chvwapConditions.isMBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isMBearish ? "conditions.chvwapConditions.isMBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isMSwitchedToBullish ? "conditions.chvwapConditions.isMSwitchedToBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isMSwitchedToBearish ? "conditions.chvwapConditions.isMSwitchedToBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isLBullish ? "conditions.chvwapConditions.isLBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isLBearish ? "conditions.chvwapConditions.isLBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isLSwitchedToBullish ? "conditions.chvwapConditions.isLSwitchedToBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isLSwitchedToBearish ? "conditions.chvwapConditions.isLSwitchedToBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isHBullish ? "conditions.chvwapConditions.isHBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isHBearish ? "conditions.chvwapConditions.isHBearish &&" + "\n" : "") +
(conditions.chvwapConditions.isHSwitchedToBullish ? "conditions.chvwapConditions.isHSwitchedToBullish &&" + "\n" : "") +
(conditions.chvwapConditions.isHSwitchedToBearish ? "conditions.chvwapConditions.isHSwitchedToBearish &&" + "\n" : "") +
"//" + "\n" +
(!conditions.chvwapConditions.hasBullishPower ? "!conditions.chvwapConditions.hasBullishPower &&" + "\n" : "") +
(!conditions.chvwapConditions.hasBearishPower ? "!conditions.chvwapConditions.hasBearishPower &&" + "\n" : "") +
(!conditions.chvwapConditions.isBullishPowerUp ? "!conditions.chvwapConditions.isBullishPowerUp &&" + "\n" : "") +
(!conditions.chvwapConditions.isBearishPowerUp ? "!conditions.chvwapConditions.isBearishPowerUp &&" + "\n" : "") +
(!conditions.chvwapConditions.isBullishPowerIncreasing ? "!conditions.chvwapConditions.isBullishPowerIncreasing &&" + "\n" : "") +
(!conditions.chvwapConditions.isBullishPowerDecreasing ? "!conditions.chvwapConditions.isBullishPowerDecreasing &&" + "\n" : "") +
(!conditions.chvwapConditions.isBearishPowerIncreasing ? "!conditions.chvwapConditions.isBearishPowerIncreasing &&" + "\n" : "") +
(!conditions.chvwapConditions.isBearishPowerDecreasing ? "!conditions.chvwapConditions.isBearishPowerDecreasing &&" + "\n" : "") +
(!conditions.chvwapConditions.isSBullish ? "!conditions.chvwapConditions.isSBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isSBearish ? "!conditions.chvwapConditions.isSBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isSSwitchedToBullish ? "!conditions.chvwapConditions.isSSwitchedToBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isSSwitchedToBearish ? "!conditions.chvwapConditions.isSSwitchedToBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isMBullish ? "!conditions.chvwapConditions.isMBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isMBearish ? "!conditions.chvwapConditions.isMBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isMSwitchedToBullish ? "!conditions.chvwapConditions.isMSwitchedToBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isMSwitchedToBearish ? "!conditions.chvwapConditions.isMSwitchedToBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isLBullish ? "!conditions.chvwapConditions.isLBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isLBearish ? "!conditions.chvwapConditions.isLBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isLSwitchedToBullish ? "!conditions.chvwapConditions.isLSwitchedToBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isLSwitchedToBearish ? "!conditions.chvwapConditions.isLSwitchedToBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isHBullish ? "!conditions.chvwapConditions.isHBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isHBearish ? "!conditions.chvwapConditions.isHBearish &&" + "\n" : "") +
(!conditions.chvwapConditions.isHSwitchedToBullish ? "!conditions.chvwapConditions.isHSwitchedToBullish &&" + "\n" : "") +
(!conditions.chvwapConditions.isHSwitchedToBearish ? "!conditions.chvwapConditions.isHSwitchedToBearish &&" + "\n" : "") +
"//" + "\n" +
")";
//
+57
View File
@@ -31,6 +31,7 @@
#include "../Helpers/x-saherelm.xchche.helper.mq5"
#include "../Helpers/x-saherelm.xchstr.helper.mq5"
#include "../Helpers/x-saherelm.xchvlm.helper.mq5"
#include "../Helpers/x-saherelm.xchvwap.helper.mq5"
//
// Base Classes ...
@@ -93,6 +94,7 @@ struct XCHStrategyConditions
XCHCHEConditions chcheConditions;
XCHSTRConditions chstrConditions;
XCHVLMConditions chvlmConditions;
XCHVWAPConditions chvwapConditions;
//
// Constructor ...
@@ -121,6 +123,7 @@ struct XCHStrategyConditions
chcheConditions.Clean();
chstrConditions.Clean();
chvlmConditions.Clean();
chvwapConditions.Clean();
}
//
@@ -226,6 +229,15 @@ struct XCHStrategyConditions
);
bullishScore += bullScore;
bearishScore += bearScore;
//
// XCHVWAP ...
chvwapConditions.GenerateScore(
bullScore,
bearScore //
);
bullishScore += bullScore;
bearishScore += bearScore;
}
//
@@ -320,6 +332,15 @@ struct XCHStrategyConditions
ignoreFalseConditions //
);
//
// XCHVWAP ...
string chvwapStr = chvwapConditions.GenerateSummary(
false,
true,
false,
ignoreFalseConditions //
);
//
string conditionsStr =
//
@@ -330,6 +351,7 @@ struct XCHStrategyConditions
chcheStr + separator +
chstrStr + separator +
chvlmStr + separator +
chvwapStr + separator +
""
//
;
@@ -607,6 +629,15 @@ public:
return result;
}
//
// XCHVWAP ...
XCHVWAPConditions chvwapConditions;
result = chvwapHelper.GetConditions(chvwapConditions);
if (!result)
{
return result;
}
//
// Start Calculations ...
@@ -654,6 +685,7 @@ public:
conditions.chstrConditions = chstrConditions;
conditions.chcheConditions = chcheConditions;
conditions.chvlmConditions = chvlmConditions;
conditions.chvwapConditions = chvwapConditions;
//
result = conditions.IsValid();
@@ -1320,6 +1352,11 @@ protected:
XCHVLMInputs chvlmInputs;
XSCXCHVLMHelper *chvlmHelper;
//
// XCHVWAP ...
XCHVWAPInputs chvwapInputs;
XSCXCHVWAPHelper *chvwapHelper;
//
//
@@ -1648,6 +1685,26 @@ private:
mPeriod,
chvlmInputs //
);
//
// XCHVWAP ...
//
chvwapInputs.Default();
//
chvwapInputs.showShort = false;
chvwapInputs.showMedium = false;
chvwapInputs.showLong = false;
chvwapInputs.showHind = false;
//
chvwapHelper = new XSCXCHVWAPHelper();
chvwapHelper.Init(
mSymbol,
mPeriod,
chvwapInputs //
);
}
//
File diff suppressed because it is too large Load Diff
-354
View File
@@ -1,354 +0,0 @@
///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XSCXTestSetupEA
// Description: provides implementation of XTest
// Setup EA ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../Test/x-saherelm.test.setup.mq5"
#include "../Classes/x-saherelm.xea.class.mq5"
//
class XSCXTestSetupEA : public XSCBaseEA
{
//
// Public ...
public:
//
// Constructors ...
XSCXTestSetupEA(
//
// XTrade Class Requirements ...
int slippage, // Specify Slippage
ulong magicNumber, // Specify Magic Number
//
// XSCTrade Event Handlers ...
TOnSignal onSignal = NULL, // On Signal Recieved Event Handler
TOnModify onModifyPosition = NULL, // On Modify Position Event Handler
TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler
TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler
TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler
TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position Event Handler
TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler
TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler
TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler
TOnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler
) : XSCBaseEA(slippage,
magicNumber,
onSignal,
onModifyPosition,
onStopLossTriggered,
onTakeProfitTriggered,
onForceClosePosition,
onPartialClosePosition,
onDealsChangedHandler,
onOrdersChangedHandler,
onPositionsChangedHandler,
onTradeStateChangedHandler //
)
{
//
DefaultConfig();
}
//
// Deconstructor ...
~XSCXTestSetupEA() {}
//
// Getter(s) / Setter(s) ...
//
double Volume()
{
return mVolume;
}
//
void Volume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mVolume = value;
}
//
bool AllowLong()
{
return mAllowLong;
}
//
void AllowLong(bool value)
{
mAllowLong = value;
}
//
bool AllowShort()
{
return mAllowShort;
}
//
void AllowShort(bool value)
{
mAllowShort = value;
}
//
// Add Setup ...
bool AddSetup(XSCXTestSetup *setup)
{
//
bool result = false;
//
result = setup != NULL;
if (!result)
{
return result;
}
//
Add(
setup,
setups //
);
//
return result;
}
//
// Overrides ...
//
// Customize Token ...
string GetToken() override
{
return GetSpecificToken(this);
}
//
string GetTag() override
{
return this.GetToken();
}
//
// Check Provider for any Guards ...
bool CheckForGuard(XGuard &guards[]) override
{
//
bool result = false;
//
return result;
}
//
// Request Fro Signals ...
int RequestForSignal(
XSignal &signals[] // Holds Signals ...
) override
{
//
int result = 0;
//
int count = CountSetups();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XTestConditions iConditions;
bool iHasConditions = setups[i].GetConditions(
iConditions,
0,
5 //
);
if (!iHasConditions)
{
continue;
}
//
// Check iConditions Signal is Valid or not ...
bool hasSignal = iConditions.signal.IsValid();
if (!hasSignal)
{
continue;
}
//
bool isLong = IsLong(iConditions.signal.type);
//
// TODO: Implement Management ...
//
AddRef(
iConditions.signal,
signals //
);
}
//
result = ArraySize(signals);
//
return result;
}
//
// Protected ...
protected:
//
// Private ...
private:
//
// Props ...
//
bool mVolume;
bool mAllowLong;
bool mAllowShort;
//
void DefaultConfig()
{
//
Volume(0.01);
AllowLong(true);
AllowShort(true);
}
//
// Provider(s) ...
//
XSCXTestSetup *setups[];
//
int CountSetups()
{
return ArraySize(setups);
}
//
int FindSetupIndex(
string _symbol //
)
{
//
int result = -1;
//
if (!IsValid(_symbol))
{
return result;
}
//
int count = CountSetups();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
bool isOwn = _symbol == setups[i].GetSymbol();
if (isOwn)
{
//
result = i;
break;
}
}
//
return result;
}
//
int FindSetupIndex(
string _symbol, //
ENUM_TIMEFRAMES _period //
)
{
//
int result = -1;
//
if (!IsValid(_symbol))
{
return result;
}
//
if (!IsValid(_period))
{
return result;
}
//
int count = CountSetups();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
bool isOwn =
_symbol == setups[i].GetSymbol() &&
_period == setups[i].GetPeriod();
if (isOwn)
{
//
result = i;
break;
}
}
//
return result;
}
//
};
//
+16
View File
@@ -84,6 +84,22 @@ if (!projectName ||
doPackProject = false;
const workSpacePath = XFileTools.joinPath(".", __dirname, "Libraries");
//
doWorkspaceCompile(workSpacePath);
}else if (projectName == "--strategies" || projectName == "**strategies") {
//
// Compile Libraries on Workspace ...
doPackProject = false;
const workSpacePath = XFileTools.joinPath(".", __dirname, "Strategies");
//
doWorkspaceCompile(workSpacePath);
}else if (projectName == "--parsers" || projectName == "**parsers") {
//
// Compile Libraries on Workspace ...
doPackProject = false;
const workSpacePath = XFileTools.joinPath(".", __dirname, "Parsers");
//
doWorkspaceCompile(workSpacePath);
} else {
+7 -5
View File
@@ -48,11 +48,13 @@ async function handlePack() {
//
var foldersPath = [
"Classes",
"Experts",
"Helpers",
"Indicators",
"Libraries"
"Classes", // Required Classes
"Experts", // Expert Advisers
"Helpers", // Indicator's Helpers Classes
"Indicators", // Required Indicators
"Libraries", // Required Libraries
"Parsers", // Strategies Filters based on Conditions
"Strategies", // Strategies Classes which Provides Signals
];
//
+6 -7
View File
@@ -15,19 +15,18 @@
"compileLibraries": "npm run compile **libraries",
"compileHelpers": "npm run compile **helpers",
"compileClasses": "npm run compile **classes",
"compileParsers": "npm run compile **parsers",
"compileStrategies": "npm run compile **strategies",
"compileIndicators": "npm run compile **indicators",
"compileProject": "npm run compileExperts && npm run compileLibraries && npm run compileHelpers && npm run compileClasses && npm run compileIndicators",
"rmExperts": "shx --silent rm ./Experts/* || npm run true",
"rmHelpers": "shx --silent rm ./Helpers/* || npm run true",
"rmClasses": "shx --silent rm ./Classes/* || npm run true",
"rmLibraries": "shx --silent rm ./Libraries/* || npm run true",
"rmIndicators": "shx --silent rm ./Indicators/* || npm run true",
"compileProject": "npm run compileIndicators && npm run compileLibraries && npm run compileHelpers && npm run compileClasses && npm run compileStrategies && npm run compileParsers && npm run compileExperts",
"rmExpertsEx": "shx --silent rm -r ./Experts/*.ex5 || npm run true",
"rmLibrariesEx": "shx --silent rm -r ./Libraries/*.ex5 || npm run true",
"rmHelpersEx": "shx --silent rm -r ./Helpers/*.ex5 || npm run true",
"rmStrategiesEx": "shx --silent rm -r ./Strategies/*.ex5 || npm run true",
"rmParsersEx": "shx --silent rm -r ./Parsers/*.ex5 || npm run true",
"rmClassesEx": "shx --silent rm -r ./Classes/*.ex5 || npm run true",
"rmIndicatorsEx": "shx --silent rm -r ./Indicators/*.ex5 || npm run true",
"cleanupEx": "npm run rmExpertsEx && npm run rmLibrariesEx && npm run rmHelpersEx && npm run rmClassesEx && npm run rmIndicatorsEx",
"cleanupEx": "npm run rmExpertsEx && npm run rmLibrariesEx && npm run rmHelpersEx && npm run rmClassesEx && npm run rmStrategiesEx && npm run rmParsersEx && npm run rmIndicatorsEx",
"prepareWorkspace": "npm run cleanupEx && npm run compileProject",
"generatePack": "npm run prepareWorkspace && npm run pack"
},