This commit is contained in:
2026-07-10 04:24:32 +03:30
parent 76f57aff36
commit 369e6f0863
25 changed files with 1679 additions and 24 deletions
@@ -1267,7 +1267,8 @@ class XCSessionDetector : public XCBase
bool isActive = IsTimeInRange( bool isActive = IsTimeInRange(
session.startTime, session.startTime,
session.endTime, session.endTime,
currentTime); currentTime //
);
// //
// Session Started // Session Started
+136
View File
@@ -0,0 +1,136 @@
# XCAccount
it is a module which used for Accoess Trading Account Data in SaherElm's XTrade Framework.
## Dependencies
there is no Dependencies on this modules.
## Instancing
there is not any args in Constructor.
## Instructions
use provided Actions for Access Account informations in where you need.
## Actions
### long GetUserAccount()
retrieve Current User Identifier.
### long GetLeverage()
retrieve Current Account Leverage.
### bool CanExpertTrade()
retrieve Flag which Specified Trading using Experts or Manual.
### ENUM_ACCOUNT_TRADE_MODE GetTradeMode()
retrieve Current Account Trading Mode.
- ACCOUNT_TRADE_MODE_DEMO;
- ACCOUNT_TRADE_MODE_CONTEST;
- ACCOUNT_TRADE_MODE_REAL;
### double GetBalance()
retrieve Current Account Balance.
### double GetCredit()
retrieve Current Account Credit.
### double GetProfit()
retrieve Current Account's Amount of Profits.
### double GetEquity()
retrieve Current Account's Amount of Equity.
### double GetMargin()
retrieve Current Account's Amount of Margin.
### double GetFreeMargin()
retrieve Current Account's Amount of Free Margin.
### double GetMarginLevel()
retrieve Current Account's Margin Level.
### double GetMarginCall()
retrieve Current Account's Margin Call Level.
### double GetMarginStopOut()
retrieve Current Account's Margin Stopout Level.
### string GetName()
retrieve Current Account's User Name.
### string GetServerName()
retrieve Current Account's Server Name.
### string GetCurrency()
retrieve Current Account's Currency.
### string GetCompany()
retrieve Current Account's Market Name.
### double CalculateTradeProfit(const string symbol, ENUM_ORDER_TYPE type, double volume, double entry, double exit)
Calculate and Retrieved Trade Profit based on Account Currency.
### double CalculateMarging(const string symbol, ENUM_ORDER_TYPE type, double volume, double entry)
Calculate and Retrieved Specified Trades used Marigin.
### double CalculateFreeMarging(const string symbol, ENUM_ORDER_TYPE type, double volume, double entry)
Calculate and Retrieved Specified Trades Free Marigin.
### double CalculateMaxVolume(const string symbol, ENUM_ORDER_TYPE type, double entry, double percent = 100)
Calculate Max Allowed Specified Trade's Volume for Entry.
### double GetPointValue(string symbol)
Retrieve Specified Symbol's Point Value.
### double CalculateRiskAmount(string symbol, double points, double volume)
Calculate How many Risk Currency in a Trade when risk Points and Trade Volume is Specified.
used when we have to know how many risk in $ Currency, for a Trade when we risk 100 Point, by Providing 0.01 Lot as Volume.
### double CalculateRiskPoints(string symbol, double volume, double amount)
Calculate Risk Points in a Trade when Volume and Curreny Amount is Specified.
used when we want to know How many points risk in a Trade when we have to risk 5$ in a Trade by 0.01 Lot as Volume.
### double CalculateVolume(string symbol, double amount, double points)
Calculate Trade Volume when Risk Amount in Currency and Risk Amount in Points Specified.
used when we want to know Open a Trade by how Size of Volume when we have to risk 5$ in a Trade when 100 points risking.
### string GetBalanceReportMessage()
Prepare and Retrieve Balance Report Message for Current Account.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+143
View File
@@ -0,0 +1,143 @@
# XCAlert
it is a module which used for Providing Logs in SaherElm's XTrade Framework.
## Dependencies
this Module used XCDataCollector for Saving Logs in Files.
## Instancing
using this syntax for instancing :
```mql5
XCAlert(
string prefix = "X-Alert", // Alerts Prefixe
bool enableAlerts = true, // Enable Alerts
bool logAlerts = true, // Log Alerts
bool terminalAlerts = false, // Terminal Alerts
bool mailAlerts = false, // Mail Alerts
bool pushAlerts = false, // Push Alerts
bool saveAlerts = false // Save Alerts
) {}
```
all of Constructor Input args is Optional, means have default values.
you can set them after instancing using Properties Setter/Getter (s).
## Instructions
- Prefix: string, Specified Logger Prefix. this for Separate Different Logger Instances.
- EnableAlerts: boolean, Specified Logging is Enabled or not.
- SaveAlerts: boolean, Specified Saving Log(s) or not.
- LogAlerts: boolean, Specified Can Print Logs on Console or not.
- TerminalAlerts: boolean, Specified Send Logs in Terminal or not.
- MailAlerts: boolean, Specified Send Logs as Mail or not.
- PushAlerts: boolean, Specified Send Logs as Push or not.
## Actions
### LogAlert(string message)
do specified type of Logs.
do log by Print in Console.
### TerminalAlert(string message)
do specified type of Logs.
do log by sending Terminal Alert.
### MailAlert(string message)
do specified type of Logs.
do log by sending Mail Alert.
### PushAlert(string message)
do specified type of Logs.
do log by sending Push Notification Alert.
### SendAlert(string message)
do sending log by configuration.
retrieve log and based on configuration send each specified enabled logs separately.
### Log(string message)
Checking Log Flag and Print Message.
### Log(string tag, string message)
Checking Log Flag and Print Specified Tag & Message.
### LogEmpty()
Checking Log Flag and Print Empty Message.
### LogArray(T &array[], string label = NULL)
Checking Log Flag and Print Array.
### LogError(int error = -1)
Checking Log Flag and then Generate Error Message based on provided error number,
then Print Tag Specified Message.
### string GetErrorDescription(int err_code)
Generate Specified Error Messaged based on Provided error code.
### string GetTradeServerReturnCodeDescription(int return_code)
Generate Specified Error Message based on Provided server error code.
### bool CanLog()
protected
return a Flag for Specified Flag which allowed Print Logs or not.
### bool CanLogAlert()
protected
return a Flag for Specified Flag which allowed Print Logs and also Enabled or not.
### bool CanTerminalAlert()
protected
return a Flag for Specified Flag which allowed Sending Logs to Terminal and also Enabled or not.
### bool CanMailAlert()
protected
return a Flag for Specified Flag which allowed Sending Logs as Mail and also Enabled or not.
### bool CanPushAlert()
protected
return a Flag for Speified Flag which allowed Sending Logs as Push and also Enabled or not.
### Save(string message)
protected
Saving Specified Message into Logger File. if alert Saving is Enabled.
#### Descriptions
- Preparing a File Name by Combining setted Prefix + ".XLogs".
- Generating File Path based on XCDataCollector instance Path.
- Validate Generated filePath.
- Preparing Log Message for Saving in Log File by attaching Current Time.
- Append prepared Message to Log File using XCDataCollector instance.
### string PrepareMessage(string message)
private
Replace Escaped strings and Attach Prefix to Message.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+80
View File
@@ -0,0 +1,80 @@
# XCDataCollector
it is a module which used for Save and Retrieve Data in SaherElm's XTrade Framework.
this tool helps all required modules to save data for next usage and analytics.
we can implement Save To File and Read From File actions to all Structures and Classes and Modules.
## Dependencies
there is no Dependencies on this modules.
## Instancing
there is not any args in Constructor.
## Instructions
- using Path Action of instance for Setting File Path;
- using Save, Append, Read for File Manipulations;
## Actions
### Path
is a Property Setter and Getter Action for Setting Collector Path.
for setter it's have an input Parameters (string value) which Specified the File's Path.
### GetFilePath(string fileName)
retrieve Full path (including provided file name) based on Current Configured Path for instance.
### GetFileHandlerForWrite(string filePath)
retrieve File Handler by Write Access for Writing Data to File.
you have to provide Fully File Path for access Handler.
this for Use Implementing Custom Collecting Senarios out of Instance Box.
commonly it's used by built in Actions for Regular Saving Data.
### GetFileHandlerForRead(string filePath)
retrieve File Handler by Read Access for Reading Data from File.
you have to provide Fully File Path for access Handler.
this for Use Implementing Custom Retrieving Senarios out of Instance Box.
commonly it's used by built in Actions for Regular Reading Data.
### Save(string fileName, string content)
Save Specified Content to Specified File Nmae.
here the file name must Contains fully file path including file name.
it's only one time writing file. if it's file exists before overwrite it's content.
### Append(string fileName, string content)
Append Specified Contonet to end of Specified File.
here the file name must Contains fully file path including file name.
if file Exists, add to end of it. if not, Create file at Specified Provided path, then write content.
### Read(string fileName, string &content)
Read all of File Content at once from Specified File.
here the file name must Contains fully file path including file name.
content arg is a reference string variable to hold file content.
### Read(string fileName, string &content[])
Read all of File Content Lines at once from Specified File.
here the file name must Contains fully file path including file name.
content arg is a reference string array variable to hold file content lines.
### IsExists(string fileName)
Check Specified File Exists or not ...
here the file name must Contains fully file path including file name.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
View File
+11
View File
@@ -0,0 +1,11 @@
# XCTrade
it is a module which used for Providing Trade Related Actions in SaherElm's XTrade Framework.
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+25
View File
@@ -0,0 +1,25 @@
# XCVolume
it is a module which used for Accoess Trading Account Data in SaherElm's XTrade Framework.
## Dependencies
there is no Dependencies on this modules.
## Instancing
there is not any args in Constructor.
## Instructions
use provided Actions for Access Account informations in where you need.
## Actions
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
View File
+19
View File
@@ -0,0 +1,19 @@
/**
* XMQL Helper CLI Tools ...
* a module for handle MQL5 Commands running ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// Read Command Arguments ...
let cmdName = process.argv[2];
//
XProjectTools.runCommand(cmdName);
@@ -0,0 +1,29 @@
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// define constants ...
const projectName = "X121XKIEA";
//
// Projects Resources ...
const projectResources = [
"Libraries/*", // Required Libraries
"Classes/*", // Required Classes
"X121XKIEA/*", // X121XKIEA Projects ...
"Indicators/x-saherelm.x121.xki", // Required Indicators
"Helpers/x-saherelm.x121.xki.helper", // Indicator's Helpers Classes
"Experts/x-saherelm.x121.xki.backtester.ea", // Expert Advisers
];
//
run();
/**
* Main Project Function ...
*/
async function run() {
//
await XProjectTools.prepareProject(projectName, projectResources);
}
@@ -0,0 +1,35 @@
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// define constants ...
const projectName = "XCATBEA";
//
// Projects Resources ...
const projectResources = [
"Libraries/*", // Required Libraries
"Classes/*", // Required Classes
"XCATBEA/*", // XCATBEA Projects ...
"Indicators/x-saherelm.x121.xcatb", // Required Indicators
"Helpers/x-saherelm.x121.xcatb.helper", // Indicator's Helpers Classes
"Experts/x-saherelm.x121.xcatb.ea", // Expert Advisers
];
//
run();
/**
* Main Project Function ...
*/
async function run() {
//
await XProjectTools.prepareProject(
projectName,
projectResources
);
}
@@ -0,0 +1,31 @@
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// define constants ...
const projectName = "XFIMAEA";
//
// Projects Resources ...
const projectResources = [
"Libraries/*", // Required Libraries
"Classes/*", // Required Classes
"XFIMAEA/*", // XOM1EA Projects ...
"Indicators/x-saherelm.xfima", // Required Indicators
"Indicators/x-saherelm.x121.xct", // Required Indicators
"Helpers/x-saherelm.xfima.helper", // Indicator's Helpers Classes
"Experts/x-saherelm.xfima.backtester.ea", // Expert Advisers
"Experts/x-saherelm.xfima.ea", // Expert Advisers
];
//
run();
/**
* Main Project Function ...
*/
async function run() {
//
await XProjectTools.prepareProject(projectName, projectResources);
}
@@ -0,0 +1,29 @@
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// define constants ...
const projectName = "XOM1EA";
//
// Projects Resources ...
const projectResources = [
"Libraries/*", // Required Libraries
"Classes/*", // Required Classes
"XOM1EA/*", // XOM1EA Projects ...
"Indicators/x-saherelm.xom1", // Required Indicators
"Helpers/x-saherelm.xom1.helper", // Indicator's Helpers Classes
"Experts/x-saherelm.xom1.ea", // Expert Advisers
];
//
run();
/**
* Main Project Function ...
*/
async function run() {
//
await XProjectTools.prepareProject(projectName, projectResources);
}
@@ -0,0 +1,27 @@
//
// Import Requirements ...
const XProjectTools = require("./x-mql-project.tools");
//
// define constants ...
const projectName = "XRRTools";
//
// Projects Resources ...
const projectResources = [
"Libraries/*", // Required Libraries
"Classes/*", // Required Classes
"Indicators/x-saherelm.x121.xcc", // Required Indicators
"Experts/x-saherelm.rr.tools", // Expert Advisers
];
//
run();
/**
* Main Project Function ...
*/
async function run() {
//
await XProjectTools.prepareProject(projectName, projectResources);
}
@@ -0,0 +1,497 @@
/**
* XProject Tools Module ...
* a module for handle MQL5 Projects Compile and Packing ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
// Import Requirements ...
const execSync = require("child_process").execSync;
const XFileTools = require("./Documents/JsModules/x-file.tools");
const XShellTools = require("./Documents/JsModules/x-shell.tools");
const XColorTools = require("./Documents/JsModules/x-color.tools");
const XTypeTools = require("./Documents/JsModules/x-type-detector.tools");
//
// Definitions ...
const packsPath = XFileTools.joinPath(".", "Packs");
const workspacePaths = [
"Classes", // Required Classes
"Experts", // Expert Advisers
"Helpers", // Indicator's Helpers Classes
"Indicators", // Required Indicators
"Libraries", // Required Libraries
"XOM1EA", // XOM1EA Projects ...
"XFIMAEA", // XOM1EA Projects ...
"XCATBEA", // XCATBEA Projects ...
"X121XKIEA", // X121XKIEA Projects ...
];
//
//#region Tools ...
/**
* Handle Compile and Pack Projects ...
*
* @param {string} projectName
* @param {string[]} resources
* @param {boolean} forceCleanup
* @param {boolean} forceCompileIndicators
*/
async function prepareProject(
projectName = "",
resources = [],
forceCleanup = true,
forceCompileIndicators = true
) {
//
// Check Resources Has Child ...
let isValidArgs =
resources.length > 0 &&
XTypeTools.isArray(resources);
if (!isValidArgs) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Invalid Resource List ...", XColorTools.COLOR_NAMES.Red)
);
}
//
// Check Project Name is Valid ...
isValidArgs =
projectName.length > 0 &&
XTypeTools.isString(projectName);
if (!isValidArgs) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Empty Project Name ...", XColorTools.COLOR_NAMES.Red)
);
}
//
// Prepare Pack Folder Exists ...
let isExists = XFileTools.isDirectoryExists(packsPath);
if (!isExists) {
XFileTools.createDirectory(packsPath);
}
//
// Check Folder Exists or not ...
// if Exists Remove it ...
// Create Project Folder on Packs ...
const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName);
isExists = XFileTools.isDirectoryExists(prjFolderOnPacks);
if (isExists) {
await XFileTools.removeDirectory(prjFolderOnPacks, true);
}
XFileTools.createDirectory(prjFolderOnPacks);
//
// Extract Required to Compile Resources List ...
let compileList = await extractResources(resources, true);
if (!compileList || compileList.length == 0) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Resource List Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red)
);
//
return;
}
//
// Compile Resources Files ...
for (const f of compileList) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue)
);
//
await recursiveTriesToCompileFile(f, 0);
}
//
// Extract Required to Pack Resources List ...
let packList = await extractResources(resources, false);
if (!packList || packList.length == 0) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Resource List Extraction to Pack Failed ...", XColorTools.COLOR_NAMES.Red)
);
//
return;
}
//
// Loop through Files ...
for (const f of packList) {
//
// Prepare Destination Path ...
const fBasePath = XFileTools.basename(f);
let fDestPath = f.replace(fBasePath, "");
fDestPath = fDestPath.substring(0, fDestPath.length - 1);
fDestPath = XFileTools.joinPath(prjFolderOnPacks, fDestPath);
//
const isFDestPathExists = XFileTools.isDirectoryExists(fDestPath);
if (!isFDestPathExists) {
XFileTools.createDirectory(fDestPath);
}
//
// Log ...
console.log(
XColorTools.applyForegroundColor("try to copy: ", XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue),
XColorTools.applyForegroundColor(" to : ", XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(fDestPath, XColorTools.COLOR_NAMES.Magenta)
);
//
let result = await XFileTools.copyFile(f, fDestPath);
if (result) {
//
const msg = "copy successfully ...";
console.log(
XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)
);
} else {
//
const msg = "copy failed ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red));
throw msg;
}
}
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Project: ", XColorTools.COLOR_NAMES.Green),
XColorTools.applyForegroundColor(projectName, XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(" Compiled and Packed Successfully ...", XColorTools.COLOR_NAMES.Green),
);
//
// Cleanup WorkSpace if Provided ...
if (forceCleanup) {
await cleanupWorkSpace();
}
//
// Compile Indicators ...
if (forceCompileIndicators) {
await runCommand("Indicators");
}
}
/**
* Extract required Files List ...
*
* @param {boolean} forCompile
*
* @returns Promise<string[]>
*/
async function extractResources(
resources = [],
forCompile = true
) {
//
let result = [];
//
// Loop Through Project Resources and Extract Files List to Compile ...
for (const resource of resources) {
//
// Prepare Normalized Resource Path ...
let resourcePath = XFileTools.joinPath(".", resource);
//
// Handle Wild Card Resources ...
if (resourcePath.endsWith("//*") ||
resourcePath.endsWith("\\*")) {
//
resourcePath = resourcePath.substring(0, resourcePath.length - 2);
const files = await XFileTools.extractFiles(
resourcePath,
forCompile ? [".mq5", ".mq4"] : [".ex5", ".ex4"]
);
//
result = result.concat(files);
}
//
// Handle Direct File Resources ...
else {
//
// Check MQL 5 Version ...
let fileResourcePath = resourcePath + (forCompile ? ".mq5" : ".ex5");
//
// Check File Exists ...
let isExists = XFileTools.isFileExists(fileResourcePath);
if (!isExists) {
//
// Check MQL 4 Version ...
fileResourcePath = resourcePath + (forCompile ? ".mq4" : ".ex4");
isExists = XFileTools.isFileExists(fileResourcePath);
}
//
// Add File Path to Files List if Exists ...
if (isExists) {
result.push(fileResourcePath);
}
}
}
//
return result;
}
/**
* try to compile a file ...
* @param {string} f
* @param {number} numberOfTries
*/
async function recursiveTriesToCompileFile(f = "", numberOfTries = 0) {
//
let result = await handleFileCompile(f);
if (result) {
//
const msg = "compiled successfully ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green));
return result;
} else {
//
if (numberOfTries < 10) {
//
numberOfTries++;
//
const msg = "retry (" + (numberOfTries + 1) + ") ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.LightMagenta));
await recursiveTriesToCompileFile(f, numberOfTries);
} else {
//
const msg = "failed ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red));
throw msg;
//
return false;
}
}
}
/**
* execute compile task on Specific File ...
* @param {string} f file path to Execute Compile task ...
* @returns
*/
async function handleFileCompile(f = "") {
//
let result = false;
//
let exResult = await compileMQLFile(f);
if (exResult.includes("0 errors")) {
result = true;
} else {
result = false;
}
//
return result;
}
/**
* Compile Specific MQL File ...
*
* @param {string} path MQL file path ...
* @returns
*/
async function compileMQLFile(path = "") {
//
// Check File Exists ...
const isExists = XFileTools.isFileExists(path);
if (!isExists) {
//
const msg = "file not found ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red));
throw msg;
}
//
const ext = XFileTools.getFileExtension(path);
if (ext !== ".mq5" && ext !== "mq4") {
//
const msg = "invalid file extension ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red));
throw msg;
}
//
const cwd = __dirname;
const cmd = "compile.cmd " + path;
//
const result = await XShellTools.execute(cmd, cwd);
return result;
}
/**
* Run Specified Command in workspace ...
*
* @param {string} cmd
* @returns
*/
async function runCommand(cmd = "") {
//
// Validate Args ...
let isValidArgs = cmd.length > 0 &&
XTypeTools.isString(cmd);
//
// Validate Commands ...
if (isValidArgs) {
//
// Check Available Commands ...
isValidArgs =
cmd === "*" ||
cmd === "cleanup" ||
workspacePaths.includes(cmd) ||
workspacePaths.map(x => x.toLowerCase(x)).includes(cmd.toLowerCase());
}
if (!isValidArgs) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red)
);
}
//
// Compile ...
if (cmd == "*") {
await compileWorkSpace();
} else if (cmd == "cleanup") {
await cleanupWorkSpace();
} else {
//
// Select Workspace to Compile ...
const folder = workspacePaths
.find(x => x.toLowerCase() === cmd.toLowerCase());
isValidArgs =
XTypeTools.isString(folder) &&
folder.length > 0;
if (!isValidArgs) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red)
);
}
//
// Extract Required to Compile Resources List ...
let compileList = await XFileTools.extractFiles(
folder,
[".mq5", ".mq4"]
);
if (!compileList || compileList.length == 0) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red)
);
//
return;
}
//
// Compile Resources Files ...
for (const f of compileList) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue)
);
//
await recursiveTriesToCompileFile(f, 0);
}
}
}
/**
* Cleanup Workspace compiled files ...
*/
async function cleanupWorkSpace() {
//
for (const path of workspacePaths) {
//
const fSourcePath = XFileTools.joinPath(".", path);
const filesToRemove = await XFileTools.extractFiles(fSourcePath, [".ex5", ".ex4"]);
for (const f of filesToRemove) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor("try to Remove: ", XColorTools.COLOR_NAMES.Yellow),
XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue)
);
//
let result = await XFileTools.removeFile(f);
if (result) {
//
const msg = "removed successfully ...";
console.log(
XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)
);
} else {
//
const msg = "removed failed ...";
console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red));
throw msg;
}
}
}
}
/**
* Compile Workspace ...
*/
async function compileWorkSpace() {
//
for (const path of workspacePaths) {
await runCommand(path);
}
}
//#endregion
//
//#region Module Exports ...
module.exports = {
extractResources,
recursiveTriesToCompileFile,
handleFileCompile,
compileMQLFile,
runCommand,
cleanupWorkSpace,
compileWorkSpace,
prepareProject
};
//#endregion
+45
View File
@@ -0,0 +1,45 @@
/**
* XMQL Document Helper CLI Tools ...
* a module for handle MQL5 Documents Generating ...
*
* Maintainer
*
* Hadi Khazaee Asl <https://saherelm.ir> (hadi_khazaee_asl@yahoo.com)
*/
//
// Import Requirements ...
const XColorTools = require("./x-color.tools");
const XDocumentTools = require("./x-mql-document.tools");
const args = process.argv.slice(2);
if (args.length < 1) {
//
// Log ...
console.log(
XColorTools.applyForegroundColor(
"Invalid Usage Command ...",
XColorTools.COLOR_NAMES.Red
)
);
console.log(
XColorTools.applyForegroundColor(
"Usage: node mql5-doc-extractor.js <path_to_mql5_file> [output_md_file]",
XColorTools.COLOR_NAMES.Yellow
)
);
console.log(
XColorTools.applyForegroundColor(
"Example: node mqlDocumentHelper.js ./MyEA.mq5 ./docs/MyEA.md",
XColorTools.COLOR_NAMES.LightBlue
)
);
//
process.exit(1);
}
const inputFile = args[0];
const outputFile = args[1] || inputFile.replace(/\.(mq5|mqh)$/i, '_DOCS.md');
XDocumentTools.extractMQL5Documentation(inputFile, outputFile);
+183
View File
@@ -0,0 +1,183 @@
const fs = require('fs');
const path = require('path');
//
//#region Tools ...
/**
* Extracts Doxygen-style documentation from MQL5 files and generates Markdown.
* @param {string} filePath - Path to the .mq5 or .mqh file
* @param {string} outputPath - Path to save the generated .md file
*/
function extractMQL5Documentation(filePath, outputPath) {
//
if (!fs.existsSync(filePath)) {
console.error(`Error: File not found at ${filePath}`);
return;
}
//
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
const extractedDocs = [];
//
let currentCommentBlock = [];
let isInsideBlockComment = false;
//
// State machine to parse comments and map them to the next line of code
for (let i = 0; i < lines.length; i++) {
//
const line = lines[i];
const trimmedLine = line.trim();
//
// 1. Handle Block Comments (/* ... */)
if (trimmedLine.startsWith('/*') || trimmedLine.startsWith('/**')) {
//
isInsideBlockComment = true;
currentCommentBlock.push(trimmedLine);
if (trimmedLine.endsWith('*/')) {
isInsideBlockComment = false;
}
continue;
}
//
if (isInsideBlockComment) {
//
currentCommentBlock.push(trimmedLine);
if (trimmedLine.endsWith('*/')) {
isInsideBlockComment = false;
}
continue;
}
//
// 2. Handle Line Comments (/// or //)
if (trimmedLine.startsWith('///') || trimmedLine.startsWith('//')) {
//
currentCommentBlock.push(trimmedLine);
continue;
}
//
// 3. Handle Empty Lines (Keep them to preserve spacing before code)
if (trimmedLine === '') {
//
if (currentCommentBlock.length > 0) {
currentCommentBlock.push('');
}
continue;
}
//
// 4. We hit actual code. If we have a comment block, map it.
if (currentCommentBlock.length > 0) {
//
// Clean up trailing empty lines in the comment block
while (currentCommentBlock.length > 0 &&
currentCommentBlock[currentCommentBlock.length - 1].trim() === ''
) {
currentCommentBlock.pop();
}
//
if (currentCommentBlock.length > 0) {
//
extractedDocs.push({
comment: currentCommentBlock.join('\n'),
code: trimmedLine
});
}
//
currentCommentBlock = [];
}
}
//
// Generate Markdown Output
generateMarkdown(filePath, extractedDocs, outputPath);
}
/**
* Formats the extracted data into a clean Markdown document.
*/
function generateMarkdown(filePath, docs, outputPath) {
//
const fileName = path.basename(filePath);
let md = `# Documentation for \`${fileName}\`\n\n`;
md += `*Extracted on: ${new Date().toLocaleDateString()}*\n\n---\n\n`;
//
let fileHeaderFound = false;
//
docs.forEach((doc, index) => {
//
// Check if this is the file-level header (usually the very first block)
if (index === 0 &&
(doc.code.startsWith('#property') || doc.code.startsWith('//+--'))) {
//
md += `## File Overview\n`;
md += formatComment(doc.comment) + '\n\n';
fileHeaderFound = true;
return;
}
//
// Only document actual functions, classes, structs, or important variables
const isDocumentableCode = /^(void|int|double|bool|string|long|ulong|uint|class|struct|enum|input)\s+/.test(doc.code)
|| doc.code.includes('class ')
|| doc.code.includes('struct ');
if (isDocumentableCode) {
//
md += `### \`${extractSignature(doc.code)}\`\n\n`;
md += `**Declaration:**\n\`\`\`cpp\n${doc.code}\n\`\`\`\n\n`;
md += `**Documentation:**\n${formatComment(doc.comment)}\n\n---\n\n`;
}
});
//
fs.writeFileSync(outputPath, md, 'utf8');
console.log(`✅ Successfully extracted documentation to: ${outputPath}`);
}
/**
* Cleans up Doxygen tags for better Markdown readability.
*/
function formatComment(comment) {
return comment
.replace(/\/\*\*?|\*\//g, '') // Remove block comment markers
.replace(/^\s*\*\s?/gm, '') // Remove leading asterisks
.replace(/^\/\/\/?\s?/gm, '') // Remove line comment markers
.replace(/@param\s+(\w+)\s*/g, '**Param `$1`:** ')
.replace(/@return\s*/g, '**Returns:** ')
.replace(/@brief\s*/g, '**Summary:** ')
.replace(/@note\s*/g, '*Note:* ')
.replace(/@warning\s*/g, '> **Warning:** ')
.trim();
}
/**
* Extracts a clean function/class signature from the code line.
*/
function extractSignature(codeLine) {
//
// Basic extraction, stops at the first opening parenthesis or brace
const match = codeLine.match(/^(.*?)[\({]/);
return match ? match[1].trim() : codeLine;
}
//#endregion
//
//#region Module Exports ...
module.exports = {
formatComment,
generateMarkdown,
extractSignature,
extractMQL5Documentation,
}
//#endregion
+23 -20
View File
@@ -24,7 +24,10 @@ const workspacePaths = [
"Helpers", // Indicator's Helpers Classes "Helpers", // Indicator's Helpers Classes
"Indicators", // Required Indicators "Indicators", // Required Indicators
"Libraries", // Required Libraries "Libraries", // Required Libraries
"XOM1EA", // XOM1EA Projects ...
"XFIMAEA", // XOM1EA Projects ...
"XCATBEA", // XCATBEA Projects ... "XCATBEA", // XCATBEA Projects ...
"X121XKIEA", // X121XKIEA Projects ...
]; ];
// //
@@ -70,6 +73,24 @@ async function prepareProject(
); );
} }
//
// Prepare Pack Folder Exists ...
let isExists = XFileTools.isDirectoryExists(packsPath);
if (!isExists) {
XFileTools.createDirectory(packsPath);
}
//
// Check Folder Exists or not ...
// if Exists Remove it ...
// Create Project Folder on Packs ...
const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName);
isExists = XFileTools.isDirectoryExists(prjFolderOnPacks);
if (isExists) {
await XFileTools.removeDirectory(prjFolderOnPacks, true);
}
XFileTools.createDirectory(prjFolderOnPacks);
// //
// Extract Required to Compile Resources List ... // Extract Required to Compile Resources List ...
let compileList = await extractResources(resources, true); let compileList = await extractResources(resources, true);
@@ -112,24 +133,6 @@ async function prepareProject(
return; return;
} }
//
// Prepare Pack Folder Exists ...
let isExists = XFileTools.isDirectoryExists(packsPath);
if (!isExists) {
XFileTools.createDirectory(packsPath);
}
//
// Check Folder Exists or not ...
// if Exists Remove it ...
// Create Project Folder on Packs ...
const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName);
isExists = XFileTools.isDirectoryExists(prjFolderOnPacks);
if (isExists) {
await XFileTools.removeDirectory(prjFolderOnPacks, true);
}
XFileTools.createDirectory(prjFolderOnPacks);
// //
// Loop through Files ... // Loop through Files ...
for (const f of packList) { for (const f of packList) {
@@ -188,7 +191,7 @@ async function prepareProject(
// //
// Compile Indicators ... // Compile Indicators ...
if (forceCompileIndicators) { if (forceCompileIndicators) {
await compile("Indicators"); await runCommand("Indicators");
} }
} }
@@ -490,5 +493,5 @@ module.exports = {
cleanupWorkSpace, cleanupWorkSpace,
compileWorkSpace, compileWorkSpace,
prepareProject prepareProject
} };
//#endregion //#endregion
+360
View File
@@ -0,0 +1,360 @@
//+------------------------------------------------------------------+
//| SmartShadowScanner.mq5 |
//| Advanced Shadow Scanner with 3-Step Checklist Filter |
//+------------------------------------------------------------------+
#property copyright "Professional Trader Setup 2026"
#property version "3.00"
#property description "Scans for large rejection shadows filtered by Sweep, POI, and Session"
//--- User Inputs
input group "=== Base Shadow Settings ==="
input double ShadowMultiplier = 2.0; // Shadow to Body Multiplier (e.g., 2.0 means shadow is 2x body)
input double MinRangeATR_Multi = 0.5; // Min Candle Range as ATR Multiplier (0.5 = 50% of ATR)
input int MinCandleSizePoints = 30; // Min Absolute Candle Size in Points (Filters micro-candles)
input ENUM_TIMEFRAMES Timeframe = PERIOD_H4; // Timeframe to Analyze
input group "=== Filter 1: Liquidity Sweep ==="
input bool EnableSweepFilter = true; // Enable Liquidity Sweep Filter
input int SwingLookback = 10; // Swing Lookback Period (Left & Right candles)
input group "=== Filter 2: Point of Interest (POI) ==="
input bool EnablePOIFilter = true; // Enable POI Filter
input int POI_ProximityPoints = 50; // Allowed Distance to POI in Points
input bool CheckPDH_PDL = true; // Check Previous Day High/Low
input bool CheckOrderBlock = true; // Check Recent Order Blocks
input group "=== Filter 3: Trading Session ==="
input bool EnableSessionFilter = true; // Enable Session Time Filter
input int LondonStartHour = 8; // London Start Hour (Server Time)
input int LondonEndHour = 12; // London End Hour (Server Time)
input int NYStartHour = 13; // New York Start Hour (Server Time)
input int NYEndHour = 18; // New York End Hour (Server Time)
input group "=== Display & Alert Settings ==="
input bool DrawArrows = true; // Draw Arrows on Chart
input bool ShowAlerts = true; // Show Popup Alerts
input bool SendPush = false; // Send Push Notifications
input color BullishArrowColor = clrLime; // Bullish Arrow Color (Lower Shadow)
input color BearishArrowColor = clrRed; // Bearish Arrow Color (Upper Shadow)
input int ArrowDistancePoints = 10; // Arrow Distance from Shadow Tip (Points)
//--- Global Variables
datetime lastBarTime = 0;
int atrHandle = INVALID_HANDLE;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize ATR indicator handle for volatility filtering
atrHandle = iATR(_Symbol, Timeframe, 14);
if(atrHandle == INVALID_HANDLE)
{
Print("Error creating ATR indicator handle!");
return(INIT_FAILED);
}
Print("=== Smart Shadow Scanner v3.0 Initialized ===");
Print("Sweep Filter: ", EnableSweepFilter ? "Enabled" : "Disabled");
Print("POI Filter: ", EnablePOIFilter ? "Enabled" : "Disabled");
Print("Session Filter: ", EnableSessionFilter ? "Enabled" : "Disabled");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up chart objects and release indicator memory
ObjectsDeleteAll(0, "ShadowArrow_");
IndicatorRelease(atrHandle);
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Process only on new bar close to avoid redundant calculations
datetime currentBarTime = iTime(_Symbol, Timeframe, 0);
if(currentBarTime == lastBarTime) return;
lastBarTime = currentBarTime;
// Copy required bars (Need enough history for Swing Lookback)
int barsNeeded = SwingLookback * 2 + 10;
MqlRates rates[];
ArraySetAsSeries(rates, true);
if(CopyRates(_Symbol, Timeframe, 0, barsNeeded, rates) < barsNeeded) return;
// Copy ATR value for the closed candle (index 1)
double atrBuffer[];
ArraySetAsSeries(atrBuffer, true);
if(CopyBuffer(atrHandle, 0, 1, 1, atrBuffer) < 1) return;
double currentATR = atrBuffer[0];
// Extract OHLC data for the target candle (index 1)
double openPrice = rates[1].open;
double highPrice = rates[1].high;
double lowPrice = rates[1].low;
double closePrice = rates[1].close;
datetime barTime = rates[1].time;
// Calculate candle metrics
double body = MathAbs(openPrice - closePrice);
double upperShadow = highPrice - MathMax(openPrice, closePrice);
double lowerShadow = MathMin(openPrice, closePrice) - lowPrice;
double totalRange = highPrice - lowPrice;
// ==========================================
// Base Filters (Volatility & Size)
// ==========================================
// Filter 1: Absolute minimum size (ignores dead-market micro candles)
if(totalRange < MinCandleSizePoints * _Point) return;
// Filter 2: Dynamic ATR filter (candle must be at least X% of average range)
if(totalRange < (currentATR * MinRangeATR_Multi)) return;
// Identify shadow type
bool isBullishShadow = (lowerShadow >= (ShadowMultiplier * body) && lowerShadow > upperShadow);
bool isBearishShadow = (upperShadow >= (ShadowMultiplier * body) && upperShadow > lowerShadow);
if(!isBullishShadow && !isBearishShadow) return;
// ==========================================
// Advanced 3-Step Checklist
// ==========================================
bool passedSweep = !EnableSweepFilter || CheckLiquiditySweep(rates, isBullishShadow);
bool passedPOI = !EnablePOIFilter || CheckNearPOI(rates, isBullishShadow, barTime);
bool passedSession = !EnableSessionFilter || CheckSession(barTime);
// Trigger final signal only if ALL enabled filters are passed
if(passedSweep && passedPOI && passedSession)
{
ProcessSignal(isBullishShadow, barTime, isBullishShadow ? lowPrice : highPrice);
}
}
//+------------------------------------------------------------------+
//| Filter 1: Check for Liquidity Sweep |
//+------------------------------------------------------------------+
bool CheckLiquiditySweep(const MqlRates &rates[], bool isBullish)
{
int targetIndex = 1; // Target candle is at index 1
if(isBullish) // For lower shadow, it must have swept a previous Swing Low
{
for(int i = targetIndex + 2; i < ArraySize(rates) - SwingLookback; i++)
{
if(IsSwingLow(rates, i, SwingLookback))
{
double swingLow = rates[i].low;
// Sweep condition: Wick pierces the swing low, but body closes above it
if(rates[targetIndex].low < swingLow && rates[targetIndex].close > swingLow)
{
return true; // Valid liquidity sweep detected
}
}
}
}
else // For upper shadow, it must have swept a previous Swing High
{
for(int i = targetIndex + 2; i < ArraySize(rates) - SwingLookback; i++)
{
if(IsSwingHigh(rates, i, SwingLookback))
{
double swingHigh = rates[i].high;
// Sweep condition: Wick pierces the swing high, but body closes below it
if(rates[targetIndex].high > swingHigh && rates[targetIndex].close < swingHigh)
{
return true; // Valid liquidity sweep detected
}
}
}
}
return false; // No valid sweep found
}
//+------------------------------------------------------------------+
//| Identify Swing High |
//+------------------------------------------------------------------+
bool IsSwingHigh(const MqlRates &rates[], int index, int lookback)
{
if(index - lookback < 0 || index + lookback >= ArraySize(rates)) return false;
double high = rates[index].high;
for(int i = 1; i <= lookback; i++)
{
if(rates[index - i].high >= high) return false;
if(rates[index + i].high >= high) return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Identify Swing Low |
//+------------------------------------------------------------------+
bool IsSwingLow(const MqlRates &rates[], int index, int lookback)
{
if(index - lookback < 0 || index + lookback >= ArraySize(rates)) return false;
double low = rates[index].low;
for(int i = 1; i <= lookback; i++)
{
if(rates[index - i].low <= low) return false;
if(rates[index + i].low <= low) return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Filter 2: Check Proximity to Point of Interest (POI) |
//+------------------------------------------------------------------+
bool CheckNearPOI(const MqlRates &rates[], bool isBullish, datetime barTime)
{
double currentPrice = isBullish ? rates[1].low : rates[1].high;
double proximity = POI_ProximityPoints * _Point;
// POI Type 1: Previous Day High / Previous Day Low (PDH/PDL)
if(CheckPDH_PDL)
{
MqlRates dayRates[];
ArraySetAsSeries(dayRates, true);
// Fetch previous daily candle data
if(CopyRates(_Symbol, PERIOD_D1, 1, 1, dayRates) >= 1)
{
double pdh = dayRates[0].high;
double pdl = dayRates[0].low;
if(isBullish && MathAbs(currentPrice - pdl) <= proximity) return true; // Near PDL
if(!isBullish && MathAbs(currentPrice - pdh) <= proximity) return true; // Near PDH
}
}
// POI Type 2: Recent Order Blocks (OB)
if(CheckOrderBlock)
{
// Scan the last 20 candles for Order Blocks
for(int i = 2; i < MathMin(20, ArraySize(rates) - 1); i++)
{
// Bullish OB: Bearish candle followed by a strong bullish displacement
if(isBullish && IsBullishOrderBlock(rates, i))
{
double obLow = rates[i].low;
double obHigh = rates[i].high;
if(currentPrice >= (obLow - proximity) && currentPrice <= (obHigh + proximity))
return true;
}
// Bearish OB: Bullish candle followed by a strong bearish displacement
if(!isBullish && IsBearishOrderBlock(rates, i))
{
double obLow = rates[i].low;
double obHigh = rates[i].high;
if(currentPrice >= (obLow - proximity) && currentPrice <= (obHigh + proximity))
return true;
}
}
}
return false; // Not near any valid POI
}
//+------------------------------------------------------------------+
//| Identify Bullish Order Block |
//+------------------------------------------------------------------+
bool IsBullishOrderBlock(const MqlRates &rates[], int index)
{
// Current candle must be bearish
if(rates[index].close >= rates[index].open) return false;
if(index - 1 < 0) return false;
// Next candle (index-1) must be a strong bullish displacement
double nextBody = MathAbs(rates[index-1].close - rates[index-1].open);
double nextRange = rates[index-1].high - rates[index-1].low;
if(rates[index-1].close <= rates[index-1].open) return false; // Must be bullish
if(nextBody < (nextRange * 0.6)) return false; // Body must be at least 60% of total range
return true;
}
//+------------------------------------------------------------------+
//| Identify Bearish Order Block |
//+------------------------------------------------------------------+
bool IsBearishOrderBlock(const MqlRates &rates[], int index)
{
// Current candle must be bullish
if(rates[index].close <= rates[index].open) return false;
if(index - 1 < 0) return false;
// Next candle (index-1) must be a strong bearish displacement
double nextBody = MathAbs(rates[index-1].close - rates[index-1].open);
double nextRange = rates[index-1].high - rates[index-1].low;
if(rates[index-1].close >= rates[index-1].open) return false; // Must be bearish
if(nextBody < (nextRange * 0.6)) return false;
return true;
}
//+------------------------------------------------------------------+
//| Filter 3: Check Trading Session Time |
//+------------------------------------------------------------------+
bool CheckSession(datetime barTime)
{
MqlDateTime dt;
TimeToStruct(barTime, dt);
int hour = dt.hour;
// London Session
if(hour >= LondonStartHour && hour < LondonEndHour) return true;
// New York Session
if(hour >= NYStartHour && hour < NYEndHour) return true;
return false; // Outside active sessions (e.g., Asian session)
}
//+------------------------------------------------------------------+
//| Process Final Signal (Draw, Alert, Push) |
//+------------------------------------------------------------------+
void ProcessSignal(bool isBullish, datetime barTime, double extremePrice)
{
string direction = isBullish ? "BULLISH" : "BEARISH";
string message = StringFormat("✅ Golden %s Signal | %s | Price: %s",
direction,
TimeToString(barTime, TIME_DATE|TIME_MINUTES),
DoubleToString(extremePrice, _Digits));
// 1. Draw Arrow on Chart
if(DrawArrows)
{
string objName = "ShadowArrow_" + IntegerToString(barTime);
int arrowCode = isBullish ? 233 : 234; // 233: Up arrow, 234: Down arrow
color arrowColor = isBullish ? BullishArrowColor : BearishArrowColor;
double arrowPrice = isBullish ?
(extremePrice - ArrowDistancePoints * _Point) :
(extremePrice + ArrowDistancePoints * _Point);
ObjectCreate(0, objName, OBJ_ARROW, 0, barTime, arrowPrice);
ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, arrowCode);
ObjectSetInteger(0, objName, OBJPROP_COLOR, arrowColor);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, 3);
ObjectSetInteger(0, objName, OBJPROP_ANCHOR, isBullish ? ANCHOR_TOP : ANCHOR_BOTTOM);
}
// 2. Trigger Alerts
if(ShowAlerts) Alert(message);
if(SendPush) SendNotification(message);
// 3. Print to Experts Log
Print(message);
}
//+------------------------------------------------------------------+
+3 -3
View File
@@ -103,7 +103,7 @@ ENUM_X_SESSION_OVERLAP_TYPE eaAllowedOverlaps[]; // Allowed Overlaps for Analysi
// //
string eaTag; // EA Scoped Tag ... string eaTag; // EA Scoped Tag ...
bool isNewBar = false; // EA Is New Bar ... bool isEaInNewBar = false; // EA Is New Bar ...
// //
XCAlert *eaAlert; // EA Scope Alert Handler ... XCAlert *eaAlert; // EA Scope Alert Handler ...
@@ -172,7 +172,7 @@ void OnTick()
// //
// Check if Is New Bar ... // Check if Is New Bar ...
isNewBar = eaBarTracker.IsNewBar(); isEaInNewBar = eaBarTracker.IsNewBar();
// //
// Check Analysis Enabled ... // Check Analysis Enabled ...
@@ -184,7 +184,7 @@ void OnTick()
{ {
// //
// Check New Bar or not ... // Check New Bar or not ...
if (!isNewBar) if (!isEaInNewBar)
{ {
return; return;
} }
+1
View File
@@ -9,6 +9,7 @@
"aab": "| Commons |", "aab": "| Commons |",
"aac": "|----------|", "aac": "|----------|",
"mqlHelper": "node mqlHelper.js", "mqlHelper": "node mqlHelper.js",
"mqlDocumentHelper": "node ./Documents/JsModules/mqlDocumentHelper.js",
"cleanupEx": "npm run mqlHelper cleanup", "cleanupEx": "npm run mqlHelper cleanup",
"compileWorkspace": "npm run mqlHelper *", "compileWorkspace": "npm run mqlHelper *",
"compileExperts": "npm run mqlHelper experts", "compileExperts": "npm run mqlHelper experts",