From f7040490c8b9ec8640ed3ab65e4772ba1203498d Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sat, 3 Aug 2024 06:14:47 +0330 Subject: [PATCH] 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 ... --- Classes/x-saherelm.xea.class.mq5 | 1806 ------------ Documents/JsModules/x-color.tools.js | 506 ++++ Documents/JsModules/x-file.tools.js | 890 ++++++ Documents/JsModules/x-shell.tools.js | 219 ++ Documents/JsModules/x-type-detector.tools.js | 268 ++ Documents/JsModules/x-value.tools.js | 1528 ++++++++++ Experts/x-strategies.ea.mq5 | 702 +++++ Experts/x-test-strategies.ea.mq5 | 9 - Helpers/x-saherelm.xchvwap.helper.mq5 | 2608 ++++++++++++++++++ Indicators/x-saherelm.xchvwap.mq5 | 830 ++++++ Parsers/x-saherelm.xch.parser.mq5 | 52 + Strategies/x-saherelm.xch.strategy.mq5 | 57 + Test/x-saherelm.test.setup.mq5 | 1779 ------------ Test/x-saherelm.test.xea.mq5 | 354 --- compile.js | 16 + pack.js | 12 +- package.json | 13 +- 17 files changed, 7689 insertions(+), 3960 deletions(-) delete mode 100644 Classes/x-saherelm.xea.class.mq5 create mode 100644 Documents/JsModules/x-color.tools.js create mode 100644 Documents/JsModules/x-file.tools.js create mode 100644 Documents/JsModules/x-shell.tools.js create mode 100644 Documents/JsModules/x-type-detector.tools.js create mode 100644 Documents/JsModules/x-value.tools.js create mode 100644 Experts/x-strategies.ea.mq5 create mode 100644 Helpers/x-saherelm.xchvwap.helper.mq5 create mode 100644 Indicators/x-saherelm.xchvwap.mq5 delete mode 100644 Test/x-saherelm.test.setup.mq5 delete mode 100644 Test/x-saherelm.test.xea.mq5 diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 deleted file mode 100644 index aacff44f..00000000 --- a/Classes/x-saherelm.xea.class.mq5 +++ /dev/null @@ -1,1806 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Class Library -// ---------------------------------------------- -// Name: XSCBaseEA -// Description: provides all Base EA requirements ... -// -// -// 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 "../Classes/x-saherelm.xalert.class.mq5" -#include "../Classes/x-saherelm.xtrade.class.mq5" - -// -// Define On Signal Event Handler Type ... -typedef void (*TOnSignal)(XSignal &signal); - -// -// Class Definition ... - -class XSCBaseEA : public XSCBaseAlert -{ - // - // Public ... -public: - // - // Props ... - - // - // Trade Class Instance ... - XSCTrade *mTrader; - - // - // Constructor ... - XSCBaseEA( - // - // XTrade Class Requirements ... - int slippage, // Specify Slippage - ulong magicNumber, // Specify Magic Number - // - // 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 - ) - { - // - // Instance XSCTrade Class ... - mTrader = new XSCTrade( - slippage, - magicNumber // - ); - - // - mIsInTestMode = IsRunningOnTestMode(); - mStaticBalanceForCalculateDrawdown = 0; // Ignore ... - - // - // Set Event Handlers ... - mOnSignal = onSignal; - mOnModifyPosition = onModifyPosition; - mOnStopLossTriggered = onStopLossTriggered; - mOnForceClosePosition = onForceClosePosition; - mOnTakeProfitTriggered = onTakeProfitTriggered; - mOnDealsChangedHandler = onDealsChangedHandler; - mOnPartialClosePosition = onPartialClosePosition; - mOnOrdersChangedHandler = onOrdersChangedHandler; - mOnPositionsChangedHandler = onPositionsChangedHandler; - mOnTradeStateChangedHandler = onTradeStateChangedHandler; - - // - if (mOnSignal != NULL) - { - AddOnSignalEventHandler(mOnSignal); - } - - // - if (mOnModifyPosition != NULL) - { - mTrader.AddOnModifyPositionEventHandler(mOnModifyPosition); - } - - // - if (mOnForceClosePosition != NULL) - { - mTrader.AddOnForceClosePositionEventHandler(mOnForceClosePosition); - } - - // - if (mOnPartialClosePosition != NULL) - { - mTrader.AddOnPartialClosePositionEventHandler(mOnPartialClosePosition); - } - - // - if (mOnStopLossTriggered != NULL) - { - mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); - } - - // - if (mOnTakeProfitTriggered != NULL) - { - mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered); - } - - // - if (mOnDealsChangedHandler != NULL) - { - mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler); - } - - // - if (mOnOrdersChangedHandler != NULL) - { - mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler); - } - - // - if (mOnPositionsChangedHandler != NULL) - { - mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler); - } - - // - if (mOnTradeStateChangedHandler != NULL) - { - mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler); - } - } - - // - // Deconstractor ... - ~XSCBaseEA() - { - // - delete mTrader; - - // - Clean(mOnSignalEventHandlers); - - // - mOnSignal = NULL; - mOnModifyPosition = NULL; - mOnStopLossTriggered = NULL; - mOnTakeProfitTriggered = NULL; - mOnForceClosePosition = NULL; - mOnDealsChangedHandler = NULL; - mOnPartialClosePosition = NULL; - mOnOrdersChangedHandler = NULL; - mOnPositionsChangedHandler = NULL; - mOnTradeStateChangedHandler = NULL; - } - - // - // Properties Getter(s) / Setter(s) ... - - // - // Retrieve Slippage ... - int GetSlippage() - { - return mTrader.GetSlippage(); - } - - // - // Retrieve Magic Number ... - ulong GetMagicNumber() - { - return mTrader.GetMagicNumber(); - } - - // - double GetDrawdownPercent() - { - // - CalculateMaxDrawdown(); - return mDrawdownPercent; - } - - // - void AddOnSignalEventHandler(TOnSignal handler) - { - // - Add( - handler, - mOnSignalEventHandlers // - ); - } - - // - double MinRequiredProfitPerTrade() - { - return mMinRequiredProfitPerTrade; - } - - // - void MinRequiredProfitPerTrade(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mMinRequiredProfitPerTrade = value; - } - - // - double MinRequiredProfitPerVolumeFactor() - { - return mMinRequiredProfitPerVolumeFactor; - } - - // - void MinRequiredProfitPerVolumeFactor(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - if (value > 0 && value < 0.01) - { - value = 0.01; - } - - // - mMinRequiredProfitPerVolumeFactor = value; - } - - // - int RestingAfterHedge() - { - return mRestingAfterHedge; - } - - // - void RestingAfterHedge(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - mRestingAfterHedge = value; - } - - // - // Overrides ... - - // - // Customize Token ... - virtual string GetToken() - { - return GetSpecificToken(this); - } - - // - virtual string GetTag() - { - return this.GetToken(); - } - - // - // Virtual Functions ... - - // - // Handle Chart Events ... - virtual void OnChartEvent( - const int id, // event ID - const long &lparam, // long type event parameter - const double &dparam, // double type event parameter - const string &sparam // string type event parameter - ) - { - } - - // - // OnTick Handler ... - virtual void OnTick() - { - // - CalculateMaxDrawdown(); - - // - // Draw ... - Draw(); - - // - // Check Trade Events ... - OnTrade(); - - // - SyncSupports(); - - // - // First Check For Any Guard Actions ... - // then Handle Guards if Provided ... - XGuard guards[]; - bool hasGuard = CheckForGuard(guards); - if (hasGuard) - { - DoGuards(guards); - } - - // - XSignal signals[]; - - // - // Second Check for Position Management or Equity Management - // Actions like Supports or etc ... - bool isIgnored = HandleStateManagement(signals); - if (isIgnored) - { - return; - } - - // - // Check Sleeping State ... - bool isSlept = IsSlept(); - if (isSlept) - { - return; - } - - // - // Second Check For Signals ... - // then Execute Signals if Provided ... - int signalsCount = RequestForSignal(signals); - if (signalsCount <= 0) - { - return; - } - - // - // Execute Signals ... - HandleSignalsExecution(signals); - - // - Clean(guards); - Clean(signals); - } - - // - // These are Some Event Handler ... - - // - // Calls whenever a signal Executed ... - virtual void OnSignalExecuted(const XSignal &signal) {} - - // - // Cals whenever a Signal Execution Failed ... - virtual void OnSignalExecutionFailed( - const XSignal &signal, - const ENUM_X_SIGNAL_EXECUTION_RESULT reason // - ) - { - } - - // - // Calls when a Position Modified ... - virtual void OnPositionModified( - const XPosition &position, - const string comment // - ) - { - } - - // - // Calls when a Position Closed ... - virtual void OnPositionClosed( - const XPosition &position, - const string comment // - ) - { - } - - // - // Calls when a Position Partially Closed ... - virtual void OnPositionPartialyClosed( - const XPosition &position, - const string comment // - ) - { - } - - // - // Handle StopLoss Event ... - virtual void OnStopLossTriggered(const XDeal &deal) {} - - // - // Handle TakeProfit Event ... - virtual void OnTakeProfitTriggered(const XDeal &deal) {} - - // - // Handle Deals Changed Event ... - virtual void OnDealsChangedHandler(int count) {} - - // - // Handle Order Changed Event ... - virtual void OnOrdersChangedHandler(int count) {} - - // - // Handle Position Changed Event ... - virtual void OnPositionsChangedHandler(int count) {} - - // - // Handle Trade State Changed ... - virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {} - - // - // Handle On Trade ... - virtual void OnTrade() - { - // - XOnTradeHandlerState state = mTrader.HandleOnTrade(); - - // - if ( - !state.hasNewDeal && - !state.hasNewOrder && - !state.hasNewPosition && - !state.hasNewHistoryOrder) - { - return; - } - - // - // STATE ... - - // - // Notfy Trade State Changed Event ... - OnTradeStateChangedHandler(state); - - // - // DEALS ... - if (state.hasNewDeal) - { - // - // Notfy Deals Changed Event ... - OnDealsChangedHandler(state.newDeals); - - // - // Retrieve Last Deal ... - XDeal deals[]; - mTrader.GetDeals(deals); - int dealsCount = ArraySize(deals); - if (dealsCount > 0) - { - // - XDeal lastDeal = deals[0]; - - // - if (lastDeal.reason == DEAL_REASON_TP) - { - OnTakeProfitTriggered(lastDeal); - } - else if (lastDeal.reason == DEAL_REASON_SL) - { - OnStopLossTriggered(lastDeal); - } - } - } - - // - // ORDERS ... - if (state.hasNewOrder || state.hasNewHistoryOrder) - { - // - // Notfy Orders Changed Event ... - OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders); - } - - // - // POSITIONS ... - if (state.hasNewPosition) - { - // - // Notfy Positions Changed Event ... - OnPositionsChangedHandler(state.newPositions); - } - } - - // - // Retrieve Dept Of Market ... - virtual void OnBookEvent(const string &symbol) - { - // - // TODO: Implement this ... - } - - // - // Draw On Chart if anything is required ... - virtual void Draw() {} - - // - // Check For any Guard Actions ... - virtual bool CheckForGuard(XGuard &guards[]) - { - return false; - } - - // - // When a Guard Notified to Do Support Signal ... - // this Method Calls For Retrieve Support Signal ... - // if it's Provided, Execute it ... - virtual bool RequestForSupport( - XSignal &support, // Holds Support Signal, if Provided - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period // Specified Time Frame - ) - { - return false; - } - - // - // Handle Position(s)/ Order(s) or EQM Supporting Action ... - // if returns true, prevent for process Tick ... - virtual bool HandleStateManagement(XSignal &signals[]) - { - return false; - } - - // - // Regulary Filtered Signals passed to this - // and here we can do Additional Signal Filtering - // for Signal Management such as (Providers and etc) ... - virtual int HandleSignalManagement(XSignal &signals[]) - { - // - int result = ArraySize(signals); - - // - return result; - } - - // - // Here we Have to Check Market based - // on our Strategy for Trading ... - // and if a Good Entry founded ... - // model it as an XSignal struct and passed it to result ... - virtual int RequestForSignal( - XSignal &signals[] // Holds Signals ... - ) - { - return 0; - } - - // - // Execute Provided Signals ... - virtual void HandleSignalsExecution(XSignal &signals[]) - { - // - int signalsCount = ArraySize(signals); - if (signalsCount <= 0) - { - return; - } - - // - int managedSignalsCount = HandleSignalManagement(signals); - if (managedSignalsCount <= 0) - { - return; - } - - // - // Notify Signal Event Handlers for Reciving New Signal ... - for (int i = 0; i < managedSignalsCount; i++) - { - NotifyOnSignalEventHandlers(signals[i]); - } - - // - // Try to Execute Signals ... - ENUM_X_SIGNAL_EXECUTION_RESULT reasons[]; - int executedSignalsCount = ExecuteSignals( - signals, - reasons // - ); - } - - // - // Tools ... - - // - // Calculate Max Drawdown and it's Percent ... - double CalculateMaxDrawdown() - { - // - int positionsCount = PositionsTotal(); - if (IsValidSize(positionsCount)) - { - double mEquity = mTrader.mAccount.GetEquity(); - if (mEquity > mMaxDrawdown) - { - mMaxDrawdown = mEquity; - } - - // - mDrawdownPercent = (mMaxDrawdown - mEquity) / (mStaticBalanceForCalculateDrawdown > 0 ? mStaticBalanceForCalculateDrawdown : mMaxDrawdown) * 100; - mDrawdownPercent = NormalizeDouble(mDrawdownPercent, 3); - } - else - { - // - mMaxDrawdown = 0.0; - mDrawdownPercent = 0.0; - } - - // - return mDrawdownPercent; - } - - // - // Protected ... -protected: - // - // Props ... - - // - // Check in Test Mode or not ... - bool mIsInTestMode; - - // - // Save Max Drawdown ... - double mMaxDrawdown; - double mDrawdownPercent; - double mStaticBalanceForCalculateDrawdown; - - // - - // - // Tools ... - - // - // Since we need to Calls Some Event Handlers on - // - Signal Execution; - // - Modified; - // - Closed; - // - Partial Closed; - // events ... - // we have to implement thouse Methods here and use them ... - - // - // Execute Stand alone Signal ... - bool ExecuteSignal( - XSignal &signal, // Signal - ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result - bool checkPolicies = true, // Check Account Policies - ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime - datetime expiration = NULL // order expiration time - ) - { - // - bool result = false; - - // - result = mTrader.ExecuteSignal( - signal, - state, - lifetime, - expiration, - checkPolicies // - ); - if (result) - { - // - OnSignalExecuted(signal); - - // - string message = "Signal Executed (" + ToString(signal.positionId) + ") Successfully ..."; - - // - Alert(message); - } - else - { - // - OnSignalExecutionFailed(signal, state); - - // // - // string message = "Signal Execution Failed: " + ToString(state) + " ..."; - - // // - // Alert(message); - } - - // - return result; - } - - // - // Execute a Collection of Signals ... - int ExecuteSignals( - XSignal &signals[], // Collection of Signal for Execution - ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result - bool checkPolicies = true, // Check Account Policies - ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime - datetime expiration = NULL // order expiration time - ) - { - // - int result = 0; - - // - int signalsCount = ArraySize(signals); - if (!IsValidSize(signalsCount)) - { - return result; - } - - // - Clean(states); - ArrayResize(states, signalsCount, X_SIGNAL_EXECUTION_UNKNOWN); - - // - for (int i = 0; i < signalsCount; i++) - { - // - bool isExecuted = ExecuteSignal( - signals[i], - states[i], - checkPolicies, - lifetime, - expiration // - ); - if (isExecuted) - { - result++; - } - } - - // - return result; - } - - // - // Modify ... - bool Modify( - ulong ticket, // position ticket - double sl = 0, // stop loss price - double tp = 0, // take profit - string comment = NULL // comment - ) - { - // - bool result = false; - - // - result = mTrader.Modify( - ticket, - sl, - tp, - comment // - ); - - // - if (result) - { - // - XPosition position; - result = mTrader.GetPosition( - ticket, - position // - ); - if (result) - { - // - OnPositionModified( - position, - comment // - ); - - // - string message = "Position " + ToString(ticket) + " Modified Successfully ..."; - - // - Alert(message); - } - } - - // - return result; - } - - // - // Close ... - bool Close( - ulong ticket, - string comment // - ) - { - // - bool result = false; - - // - XPosition position; - result = mTrader.GetPosition( - ticket, - position // - ); - - // - result = mTrader.Close( - ticket, - comment // - ); - - // - if (result) - { - // - OnPositionClosed( - position, - comment // - ); - - // - string message = "Position " + ToString(ticket) + " Closed Successfully ..."; - - // - Alert(message); - } - - // - return result; - } - - // - // Close ... - int Close( - XPosition &positions[], - string comment // - ) - { - // - int result = 0; - - // - int count = ArraySize(positions); - if (!IsValidSize(count)) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isClosed = Close( - positions[i].ticket, - comment // - ); - - // - if (isClosed) - { - result++; - } - } - - // - return result; - } - - // - // Partial Close ... - bool PartialClose( - ulong ticket, - double volume, - string comment // - ) - { - // - bool result = false; - - // - XPosition position; - result = mTrader.GetPosition( - ticket, - position // - ); - if (!result) - { - return result; - } - - // - result = mTrader.ClosePartial( - ticket, - volume, - comment // - ); - - // - if (result) - { - // - OnPositionPartialyClosed( - position, - comment // - ); - - // - string message = "Position " + ToString(ticket) + " Successfully Closed Parital ..."; - - // - Alert(message); - } - - // - return result; - } - - // - // Partial Close ... - int PartialClose( - XPosition &positions[], - double volume, - string comment // - ) - { - // - int result = 0; - - // - int count = ArraySize(positions); - if (!IsValidSize(count)) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isClosed = PartialClose( - positions[i].ticket, - volume, - comment // - ); - - // - if (isClosed) - { - result++; - } - } - - // - return result; - } - - // - int CancelOrders() - { - // - int result = 0; - - // - XOrder supports[]; - int supportsCount = mTrader.GetOrders( - supports, - NULL, // All Symbols ... - XEQMSupportToken, // Only EQM Supports ... - NULL, // All Periods ... - X_POSITION_TYPE_ALL, // All Order Types ... - ORDER_STATE_PLACED, // Untriggered Orders ... - true // Filter by Magic ... - ); - if (!IsValidSize(supportsCount)) - { - return result; - } - - // - result = mTrader.CancelOrders( - supports // - ); - - // - Clean(supports); - - // - return result; - } - - // - // Search Positions and Remove - // non Exists Positions Support Orders ... - void SyncSupports() - { - // - XOrder orders[]; - int ordersCount = mTrader.GetOrders( - orders, - NULL, // All Symbols ... - NULL, // All Providers ... - NULL, // All Periods ... - X_POSITION_TYPE_ALL, // All Types ... - ORDER_STATE_PLACED, // Placed Untriggered Orders ... - true // Filter by Magic ... - ); - if (!IsValidSize(ordersCount)) - { - return; - } - - // - XPosition positions[]; - int positionsCount = mTrader.GetPositions( - positions // - ); - if (!IsValidSize(positions)) - { - // - mTrader.CancelOrders(orders); - return; - } - - // - XOrder mustCancel[]; - for (int i = 0; i < ordersCount; i++) - { - // - XOrder iOrder = orders[i]; - - // - // Check Order is Support or not ... - ulong iParentTicket = ExtractSupportedTicket(iOrder.comment); - if (iParentTicket <= 0) - { - continue; - } - - // - // We Sure it is support Order ... - XPosition parent; - bool isParentExists = mTrader.GetPosition( - iParentTicket, - parent // - ); - if (!isParentExists) - { - // - AddRef( - iOrder, - mustCancel // - ); - } - } - - // - int mustCancelCount = ArraySize(mustCancel); - if (!IsValidSize(mustCancelCount)) - { - return; - } - - // - mTrader.CancelOrders(mustCancel); - - // - Clean(orders); - Clean(positions); - Clean(mustCancel); - } - - // - // Hedging ... - - // - // Check Required Properties Setted for Hedge or not ... - bool AllowHedge() - { - // - bool result = false; - - // - result = - // - mMinRequiredProfitPerTrade > 0 && - mMinRequiredProfitPerVolumeFactor > 0 - // - ; - - // - return result; - } - - // - // Check Hedge Conditions is Happens or not ... - // if true doing Hedge ... - bool DoHedge() - { - // - bool result = false; - - // - result = AllowHedge(); - if (!result) - { - return result; - } - - // - XPosition positions[]; - int positionsCount = mTrader.GetPositions(positions); - result = positionsCount > 1; - if (!result) - { - return result; - } - - // - // Check At Least One Support Positions Open For Hedging ... - // XPosition supports[]; - // int supportsCount = ExtractSupports( - // positions, - // supports // - // ); - // result = IsValidSize(supportsCount); - // if (!result) - // { - // return result; - // } - - // - double profits = SpecifiedCalculatePositionsProfit(positions); - double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( - positions, - mMinRequiredProfitPerTrade, - mMinRequiredProfitPerVolumeFactor // - ); - - // - result = - positionsCount <= 5 - ? profits >= requiredProfit - : profits >= requiredProfit * 0.6; - if (!result) - { - return result; - } - - // - string comment = XEQMSupportToken + " Hedge ..."; - - // - int closed = Close( - positions, - comment // - ); - result = IsValidSize(closed); - if (!result) - { - return result; - } - - // - SyncSupports(); - - // - string message = XEQMSupportToken + " Hedge: " + ToString(profits) + " ..."; - - // - Alert(message); - - // - if (mRestingAfterHedge > 0) - { - Sleeping(mRestingAfterHedge); - } - - // - return result; - } - - // - // Signal Event Listeners ... - - // - void NotifyOnSignalEventHandlers(XSignal &signal) - { - // - int listenersCount = ArraySize(mOnSignalEventHandlers); - if (listenersCount <= 0) - { - return; - } - - // - for (int i = 0; i < listenersCount; i++) - { - // - TOnSignal iListener = mOnSignalEventHandlers[i]; - - // - iListener(signal); - } - } - - // - // Guards ... - - // - // Do All Provided Guards ... - void DoGuards(XGuard &guards[]) - { - // - int guardsCount = ArraySize(guards); - if (guardsCount <= 0) - { - return; - } - - // - for (int i = 0; i < guardsCount; i++) - { - // - XGuard iGuard = guards[i]; - - // - switch (iGuard.action) - { - // - // Hedge In Profit Specified Positions ... - case X_GUARD_ACTION_HEDGE: - HandleGuardHedgeAction( - iGuard.provider, - iGuard.symbol, - iGuard.type, - iGuard.period); - break; - - // - // Trail Stop Loss in Specified Positions ... - case X_GUARD_ACTION_TRAIL_STOP: - HandleGuardTrailingStopAction( - iGuard.provider, - iGuard.symbol, - iGuard.type, - iGuard.period, - iGuard.dblPayLoad); - break; - - // - // Force Close Specified Positions ... - case X_GUARD_ACTION_FORCE_CLOSE: - HandleGuardForceCloseAction( - iGuard.provider, - iGuard.symbol, - iGuard.type, - iGuard.period); - break; - - // - // Generate and Place Support Signals ... - case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: - HandleGuardAddSupportPositionAction( - iGuard.provider, - iGuard.symbol, - iGuard.type, - iGuard.period); - break; - - // - // Delete All Placed Pending Orders ... - case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: - HandleGuardCancelPendingOrdersAction( - iGuard.provider, - iGuard.symbol, - iGuard.type, - iGuard.period); - break; - } - } - } - - // - // Close All Specified Provider's Positions in Profit Summary ... - void HandleGuardHedgeAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period, // Specified Time Frame - double minProfitForHedging = 1, // Specified Profit for Hedge - double minProfitForHedgingVolumeFactor = 0.01 // Specified Volume Factor for Hedge - ) - { - // - XPosition positions[]; - int positionsCount = mTrader - .GetPositions( - positions, - symbol, - provider, - period, - type - // - ); - if (positionsCount <= 1) - { - return; - } - - // - double profit = SpecifiedCalculatePositionsProfit(positions); - double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( - positions, - minProfitForHedging, - minProfitForHedgingVolumeFactor // - ); - - // - bool isReadyForHedge = profit >= requiredProfit; - if (!isReadyForHedge) - { - return; - } - - // - string comment = "Guard Hedge " + provider; - int closed = mTrader.Close( - positions, - comment - // - ); - if (closed > 0) - { - // - string message = "Guard Hedge " + provider + "'s Positions on Profit: " + ToString(profit); - - // - Alert(message); - } - } - - // - // Close Max In Profit Trade Guard Action ... - void HandleGuardCloseInProfitAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period, // Specified Time Frame - ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method - ) - { - // - XPosition positions[]; - int positionsCount = mTrader - .GetInProfitPositions( - positions, - symbol, - provider, - period, - type, - method - // - ); - if (positionsCount <= 0) - { - return; - } - - // - string comment = "Close InProfit ..."; - mTrader.Close( - positions, - comment - // - ); - - // - string message = "Guard Close (" + ToString(positionsCount) + ") Postion(s) In Profit ..."; - - // - Alert(message); - } - - // - // Close Max In Drawdown Trade Guard Action ... - void HandleGuardCloseInDrawdownAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period, // Specified Time Frame - ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method - ) - { - // - XPosition positions[]; - int positionsCount = mTrader - .GetInDrawdownPositions( - positions, - symbol, - provider, - period, - type, - method - // - ); - if (positionsCount <= 0) - { - return; - } - - // - string comment = "Close InDrawdown ..."; - mTrader.Close( - positions, - comment - // - ); - - // - string message = "Guard Close (" + ToString(positionsCount) + ") Position(s) In Drawdown ..."; - - // - Alert(message); - } - - // - // Force Close Specified Set Of Position ... - void HandleGuardForceCloseAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period, // Specified Time Frame - ulong ticket = 0 // Specific Ticket - ) - { - // - string comment = ""; - - // - // Close All Positions ... - if (ticket == 0) - { - // - XPosition positions[]; - int positionsCount = mTrader.GetPositions( - positions, - symbol, - provider, - period, - type - // - ); - if (positionsCount <= 0) - { - return; - } - - // - comment = provider + " Force Close Guard ..."; - - // - mTrader.Close( - positions, - comment - // - ); - } - // - // Close Specific Position ... - else - { - // - XPosition position; - bool hasPosition = mTrader - .GetPosition( - ticket, - position - // - ); - - // - if (hasPosition) - { - // - comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ..."; - - // - mTrader.Close( - ticket, - comment - // - ); - } - } - - // - if (IsValid(comment)) - { - Alert(comment); - } - } - - // - // Trailing Specified Set Of Positions Stop Losses ... - void HandleGuardTrailingStopAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period, // Specified Time Frame - double sl // Desired SL Value ... - ) - { - // - if (sl <= 0) - { - return; - } - - // - NormalizePrice( - sl, - symbol - // - ); - - // - XPosition positions[]; - int positionsCount = mTrader - .GetPositions( - positions, - symbol, - provider, - period, - type - // - ); - if (positionsCount <= 0) - { - return; - } - - // - int modified = 0; - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - string comment = PrepareSLTrailTag(iPosition.comment); - - // - if (iPosition.sl == sl) - { - continue; - } - - // - bool isModified = mTrader.Modify( - iPosition.ticket, - sl, - iPosition.tp, - comment); - if (isModified) - { - modified++; - } - } - - // - if (modified > 0) - { - // - string message = "(" + ToString(modified) + ") Position's Stop Trailed Successfully ..."; - - // - Alert(message); - } - } - - // - // Add Support Signal for Specified Positions ... - void HandleGuardAddSupportPositionAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period // Specified Time Frame - ) - { - // - XSignal support; - bool hasSupport = RequestForSupport( - support, - provider, - symbol, - type, - period - // - ); - - // - if (!hasSupport || !support.IsValid()) - { - return; - } - - // - // TODO: May be need to add Support Tag to comments ... - - // - ENUM_X_SIGNAL_EXECUTION_RESULT reason = NULL; - bool isExecuted = ExecuteSignal( - support, - reason // - ); - - // - string comment = NULL; - if (!isExecuted) - { - comment = "Support Execution Failed doue " + ToString(reason); - } - else - { - comment = "Guard Support Signal Executed Successfully ..."; - } - - // - if (IsValid(comment)) - { - Alert(comment); - } - } - - // - // Cancel all Placed Orders ... - void HandleGuardCancelPendingOrdersAction( - string provider, // Positions Provided by Specific Provider - string symbol, // Trading Symbol - ENUM_X_POSITION_TYPES type, // Trading Type - ENUM_TIMEFRAMES period // Specified Time Frame - ) - { - // - XOrder orders[]; - int ordersCount = mTrader.GetOrders( - orders, - symbol, - provider, - period, - type, - ORDER_STATE_PLACED, - true // Filter by Magic ... - // - ); - if (ordersCount <= 0) - { - return; - } - - // - int canceledOrdersCount = mTrader.CancelOrders(orders); - - // - if (canceledOrdersCount > 0) - { - // - string message = "Guard Cancel (" + ToString(canceledOrdersCount) + ") Pending Orders ..."; - - // - Alert(message); - } - } - - // - // Sleeping Context ... - - // - // Sleeping Mode ... - int mSleepingDuration; - datetime mSleepingStartAt; - bool Sleeping(int seconds = -1) - { - // - bool result = false; - - // - mSleepingDuration = - seconds > 0 - ? seconds - : mRestingAfterHedge > 0 - ? mRestingAfterHedge - : 0; - result = mSleepingDuration > 0; - if (!result) - { - // - ResetSleeping(); - return result; - } - - // - // Check Doesnt Sleep Before ... - result = mSleepingStartAt == NULL; - if (!result) - { - // - ResetSleeping(); - return result; - } - - // - datetime cTime = TimeCurrent(); - mSleepingStartAt = cTime; - - // - return result; - } - bool IsSlept() - { - // - bool result = false; - - // - result = mSleepingDuration > 0 && - mSleepingStartAt != NULL; - if (!result) - { - // - ResetSleeping(); - return result; - } - - // - datetime cTime = TimeCurrent(); - result = (int)cTime < (int)mSleepingStartAt + mSleepingDuration; - if (!result) - { - ResetSleeping(); - } - - // - return result; - } - void ResetSleeping() - { - // - mSleepingDuration = 0; - mSleepingStartAt = NULL; - } - - // - // Private ... -private: - // - // Props ... - - // - int mRestingAfterHedge; // Resting Bars After Hedge - double mMinRequiredProfitPerTrade; // Minimum Required Profit for Hedging - double mMinRequiredProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Velume - - // - // Signal Event Listeners ... - TOnSignal mOnSignalEventHandlers[]; - - // - // Event Handlers ... - TOnSignal mOnSignal; - TOnModify mOnModifyPosition; - TOnStopLoss mOnStopLossTriggered; - TOnTakeProfit mOnTakeProfitTriggered; - TOnForceClose mOnForceClosePosition; - TOnDealsChanged mOnDealsChangedHandler; - TOnPartialClose mOnPartialClosePosition; - TOnOrdersChanged mOnOrdersChangedHandler; - TOnPositionsChanged mOnPositionsChangedHandler; - TOnTradeStateChanged mOnTradeStateChangedHandler; -}; - -// \ No newline at end of file diff --git a/Documents/JsModules/x-color.tools.js b/Documents/JsModules/x-color.tools.js new file mode 100644 index 00000000..c3ac5f9e --- /dev/null +++ b/Documents/JsModules/x-color.tools.js @@ -0,0 +1,506 @@ +/** + * XColor Tools Module ... + * a module for handle colorify text contents in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (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 \ No newline at end of file diff --git a/Documents/JsModules/x-file.tools.js b/Documents/JsModules/x-file.tools.js new file mode 100644 index 00000000..011c98bd --- /dev/null +++ b/Documents/JsModules/x-file.tools.js @@ -0,0 +1,890 @@ +/** + * XFile Tools Module ... + * a module for handle all file/folder manipulating task in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (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} 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} 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} 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} 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} 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} + */ +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} 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} 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} 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} 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} 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} + */ +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 \ No newline at end of file diff --git a/Documents/JsModules/x-shell.tools.js b/Documents/JsModules/x-shell.tools.js new file mode 100644 index 00000000..0ee13de9 --- /dev/null +++ b/Documents/JsModules/x-shell.tools.js @@ -0,0 +1,219 @@ +/** + * XShell Tools Module ... + * a module for handling shell actions and retrieve OS Info in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (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 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 \ No newline at end of file diff --git a/Documents/JsModules/x-type-detector.tools.js b/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 00000000..86ed3d80 --- /dev/null +++ b/Documents/JsModules/x-type-detector.tools.js @@ -0,0 +1,268 @@ +/** + * DataType Tools Module ... + * a module for manipulate and detect supported data types in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (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 \ No newline at end of file diff --git a/Documents/JsModules/x-value.tools.js b/Documents/JsModules/x-value.tools.js new file mode 100644 index 00000000..81cfcc4b --- /dev/null +++ b/Documents/JsModules/x-value.tools.js @@ -0,0 +1,1528 @@ +/** + * Value Tools Module ... + * a module for Validate args and values ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const XTypeTools = require('./x-type-detector.tools'); +//#endregion + +// +//#region Actions ... +/** +* validate a value as an argument ... +* +* @param {string} value the value which going to validate ... +* @returns +*/ +function isValidArg(value) { + // + let result = false; + + // + result = value && + value.length > 0; + + // + return result; +} + +/** + * validate a collection of valuea as an arguments ... + * + * @param {string|string[]} values the value collection which going to checked ... + * @returns + */ +function isValidArgs(values) { + // + // Normalize Values ... + const normalValues = toNormalArray(values); + if (!hasChildArray(normalValues)) { + return false; + } + + // + let result = normalValues.every(nv => isValidArg(nv)); + return result; +} + +/** + * converts content to an array object ... + * + * @param {string|string[]} content the content which required to normalized ... + * @returns {string[]} array object ... + */ +function toNormalArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + const result = Array.isArray(content) ? + [...content] : + content.includes(',') && + content !== ',' ? + [...content.split(',')] : + [content]; + + // + return result; +} + +/** + * determines value is array and has atleast one child ... + * + * @param {any} value the value which going to checked ... + * @returns {boolean} result of checking ... + */ +function hasChildArray(value) { + // + let result = false; + result = value && + Array.isArray(value) && + value.length > 0; + + // + return result; +} + +/** + * check an string is ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} value specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function endsWidth( + symbol = '', + value = '', + ignoreCase = true +) { + // + if (!isValidArg(value)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + // TODO: uncomment it if necessary ... + // symbol = symbol.trim(); + + // + let result = false; + const subtractedContent = value.substring(value.length - symbol.length); + result = !!ignoreCase ? + subtractedContent + .toLowerCase() === symbol + .toLowerCase() : + subtractedContent === symbol; + + // + return result; +} + +/** + * surround specified content by provided symbol ... + * + * @param {string} symbol surround string ... + * @param {string} content used content to surrounded by symbol ... + * @returns surrounded content ... + */ +function surroundBy( + symbol = '', + content = '' +) { + // + // Validate Args ... + if (!isValidArg(content)) { + content = ''; + } + + // + if (!isValidArg(symbol)) { + symbol = ''; + } + + // + if (isSurrounded(symbol, content)) { + return content; + } + + // + const result = `${symbol}${content}${symbol}`; + return result; +} + +/** + * convert a parsed sign to clear string ... + * + * @param {string} value a parsed content ... + * @returns clear parsed signs ... + */ +function toStringExpression(value) { + // + let result = ''; + result = value; + + // + if ( + !value || + !isValidArg(value) || + !isSurroundedString(value) + ) { + return result; + } + + // + const startSymbol = value.charAt(0); + const endSymbol = value.charAt(value.length - 1); + + // + if (startSymbol !== endSymbol) { + return result; + } + + // + if ( + startSymbol === "\"" || + startSymbol === "\'" + ) { + result = clearSurround(startSymbol, value); + } + + // + return result; +} + + + +/** + * find and cleare proposed candidates from specified content ... + * + * @param {string|string[]} candidates the proposed string(s) whic going to cleared from content ... + * @param {string} content the destination content which used to find and replace candidates on it ... + * @returns cleared content ... + */ +function clearContent( + candidates, + content +) { + // + // Validate Args ... + if ( + !candidates || + !isValidArg(content) + ) { + return ''; + } + + // + // Normalize candidates ... + const normalCandidates = toNormalArray(candidates) + .filter(c => isValidArg(c)); + if (!hasChildArray(normalCandidates)) { + return content; + } + + // + // define regexp for content ... + const regExpExpression = normalCandidates.join('|'); + const regExp = new RegExp( + regExpExpression, + 'gi' + ); + + // + let result = ''; + result = content.replace(regExp, ''); + + // + return result; +} + +/** + * clear surrounded symbol from content ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified content to clear ... + * @returns + */ +function clearSurround( + symbol = '', + content = '' +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + (isValidArg(symbol) && + symbol.length >= content.length - 1) + ) { + return ''; + } + + // + // Validate Surround ... + if (!isSurrounded(symbol, content)) { + return content; + } + + // + if (!isValidArg(symbol)) { + return content; + } + + // + let result = content.substring(symbol.length, content.length - symbol.length); + return result; +} + +/** + * clear object sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearObjectSurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedObject(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth('}', content) ? + 1 : + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * clear array sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearArraySurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedArray(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth(']', content) ? + 1 : + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * slice a content to individual parts ... + * + * @param {number|number[]} indexes which indexes used to slice ... + * @param {strng} content the content which going to sliced ... + * @returns sliced parts of content ... + */ +function sliceContent(indexes, content) { + // + // Validate Args ... + if ( + !isValidArg(indexes) || + !isValidArg(content) + ) { + return []; + } + + // + // Normalize indexes ... + const normalIndexes = toNormalArray(indexes) + .filter(index => index > -1 && index < content.length); + if (!hasChildArray(normalIndexes)) { + return []; + } + + // + let result = ['']; + result.pop(); + + // + let lastIndex = 0; + for (const index of normalIndexes) { + // + const part = content.substring(lastIndex, index); + if (isValidArg(part)) { + result.push(part.trim()); + } + + // + lastIndex = index + 1; + } + + // + // check remained parts ... + if (lastIndex < content.length) { + // + const part = content.substring(lastIndex); + if (isValidArg(part)) { + result.push(part.trim()); + } + } + + // + return result; +} + + + +/** + * check an string is starts and ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function isSurrounded( + symbol = '', + content = '', + ignoreCase = true +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + symbol = symbol.trim(); + + // + let result = false; + result = (!!ignoreCase ? + content + .toLowerCase() + .startsWith(symbol.toLowerCase()) : + content.startsWith(symbol) + ) && + endsWidth(symbol, content, ignoreCase); + + // + return result; +} + +/** + * determines a content is an string surrounded value or not ... + * + * @param {string} content a content which going to check ... + * @returns + */ +function isSurroundedString(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = ( + content.startsWith('\'') && + ( + endsWidth('\'', content) || + endsWidth('\',', content) || + endsWidth('\';', content) || + endsWidth('\'\n', content) + ) || + content.startsWith('\"') && + ( + endsWidth('\"', content) || + endsWidth('\",', content) || + endsWidth('\";', content) || + endsWidth('\"\n', content) + ) || + content.startsWith('`') && + ( + endsWidth('\`', content) || + endsWidth('\`,', content) || + endsWidth('\`;', content) || + endsWidth('\`\n', content) + ) + ); + return result; +} + +/** + * check a content is an array content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('[') && + ( + endsWidth(']', content) || + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) + ); + return result; +} + +/** + * check a content is an object content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedObject(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('{') && + ( + endsWidth('}', content) || + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) + ); + return result; +} + +/** + * check an index model is contains inside anothers or not ... + * + * @param {{ start: number, end: number}} source the source index model to check ... + * @param {...{ start: number, end: number}} dest the collection of index models which going to check ... + * @returns + */ +function isIndexInside(source, ...dest) { + // + let result = false; + + // + // Validate Args ... + if (!source || !dest) { + return result; + } + + // + // Check idx is standard ... + if ( + !source || + !source.end || + !source.start || + source.start > source.end + ) { + return false; + } + + // + // Check types of destinations ... + for (let index of dest) { + // + // Check idx is standard ... + if ( + !index || + !index.end || + !index.start || + index.start > index.end + ) { + return false; + } + } + + // + if (dest.includes(source)) { + dest = dest.filter(d => d !== source); + } + + // + const insideContentIndex = dest.find(dIndex => { + // + const result = source.start >= dIndex.start && + source.start <= dIndex.end && + source.end >= dIndex.start && + source.end <= dIndex.end; + return result; + }); + + // + result = insideContentIndex; + return result; +} + +/** + * check a number exists in + * @param {number} idx the number which going to check ... + * @param {{ start: number, end: number}} index the index model + * @returns + */ +function isInsideIndex(idx = -1, index) { + // + let result = false; + + // + // Validate Args ... + if ( + !index || + !index.hasOwnProperty('end') || + !index.hasOwnProperty('start') + ) { + return result; + } + + // + result = idx > index.start && idx < index.end; + return result; +} + +/** + * determines an object is key/value and type ... + * + * @param {any} content the object which we are going to check ... + * @returns + */ +function isKeyValueType(content) { + // + const result = content && + content.hasOwnProperty('key') && + content.hasOwnProperty('type') && + content.hasOwnProperty('value'); + + // + return result; +} + + + +/** + * find all indexes of token(s) in content ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns {number[]} all occured indexes ... + */ +function findAllIndexes( + tokens, + content +) { + // + // Validate Args ... + if ( + !isValidArg(tokens) || + !isValidArg(content) + ) { + return []; + } + + // + // normalize tokens ... + const normalTokens = toNormalArray(tokens); + if (!hasChildArray(normalTokens)) { + return []; + } + + // + // Parse contents ... + let match; + const result = []; + const regExp = new RegExp( + normalTokens.join('|'), + 'g' + ); + while ((match = regExp.exec(content)) !== null) { + result.push(match.index); + } + if (!hasChildArray(result)) { + return []; + } + + // + return result; +} + +/** + * find nearest symbol in a content from specified index ... + * + * @param {string|string[]} candidates specifies which symbols to find ... + * @param {string} content te content for seasrch ... + * @param {number} startFromIndex the index of start position ... + * @returns + */ +function findNearest( + candidates, + content = '', + startFromIndex = 0 +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) || + !isValidArg(content.trim()) + ) { + return ''; + } + + // + // Normalize Content ... + content = content.trim(); + + // + // Normalize Starts From ... + startFromIndex = startFromIndex < 0 || startFromIndex > content.length - 1 ? 0 : startFromIndex; + + // + // Normalize Symbols ... + const normalCandidates = toNormalArray(candidates); + if (!hasChildArray(normalCandidates)) { + return ''; + } + + // + let nearestIndex = findNearestIndex( + normalCandidates, + content, + startFromIndex + ); + if (nearestIndex < 0) { + return ''; + } + + // + let result = content.substring( + nearestIndex, + nearestIndex + Math.max(...normalCandidates.map(nc => nc.length)) + ).trim(); + return result; +} + +/** + * search candidates in content and find nearest one and return it ... + * + * @param {string|string[]} candidates which candidates required to check ... + * @param {string} content the content which required to search candidates ... + * @param {number} startFromIndex the proposed index to start searching content from on ... + * @returns + */ +function findNearestIndex( + candidates = [''], + content = '', + startFromIndex = 0, + ignoreClosedItems = false +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) + ) { + return -1; + } + + // + // Mormalize startFromIndex value ... + startFromIndex = startFromIndex < 0 ? + 0 : + startFromIndex > content.length - 1 ? + content.length - 1 : + startFromIndex; + + // + // Normalize candidates ... + let normalCandidates = toNormalArray(candidates); + + // + if (!!ignoreClosedItems) { + normalCandidates = normalCandidates + .map(c => content.indexOf( + c, + startFromIndex + ) + ).map(c => +c) + .filter(c => +c > -1); + } else { + normalCandidates = findAllIndexesOutOfCloseds(normalCandidates, content) + .filter(c => c >= startFromIndex); + } + if (!hasChildArray(normalCandidates)) { + return -1; + } + + // + let result = -1; + result = Math.min(...normalCandidates); + + // + return result; +} + +/** + * find close index of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findCloseIndex( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = -1 +) { + // + // Validate Args ... + if ( + startsFrom < 0 || + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + openSymbol === closeSymbol || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + startsFrom > content.length - 1 + ) { + return -1; + } + + // + let result = -1; + + // + let index = startsFrom; + const openSignStack = []; + while (index < content.length) { + // + const openCandidate = content.substring(index, index + openSymbol.length); + const closeCandidate = content.substring(index, index + closeSymbol.length); + + // + if (openCandidate === openSymbol) { + openSignStack.push(index); + } else if (closeCandidate === closeSymbol) { + // + if (openSignStack.length > 0) { + openSignStack.pop(); + } + + // + if (openSignStack.length === 0) { + result = index; + break; + } + } + + // + index++; + } + + // + return result; +} + +/** + * find closed contents of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findClosedContent( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = 0, +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + openSymbol.length >= content.length || + closeSymbol.length >= content.length + ) { + return result; + } + + // + // Normalize Start From ... + startsFrom = startsFrom < 0 || startsFrom >= content.length ? 0 : startsFrom; + + // + let canContinue = true; + while (!!canContinue) { + // + let openSymbolIndex = content.indexOf(openSymbol, startsFrom); + if (openSymbolIndex < 0) { + // + canContinue = false; + continue; + } + + // + let closeSymbolIndex = findCloseIndex( + openSymbol, + closeSymbol, + content, + openSymbolIndex + ); + if (closeSymbolIndex < 0) { + // + canContinue = false; + continue; + } + if (content.charAt(closeSymbolIndex) !== closeSymbol) { + closeSymbolIndex++; + } + + // + // Prevent ${} string interpolations ... + if ( + openSymbol === '{' && + openSymbolIndex - 1 >= 0 + ) { + // + const prevChar = content.charAt(openSymbolIndex - 1); + if (prevChar === '$') { + continue; + } + } + + // + const item = content + .substring(openSymbolIndex, closeSymbolIndex + 1) + .trim(); + startsFrom = closeSymbolIndex + 1; + result.push({ + start: openSymbolIndex, + end: closeSymbolIndex, + content: item + }); + } + + // + if (!hasChildArray(result)) { + return result; + } + + // + return result; +} + +/** + * extract a collection of closed contents exists in a content ... + * + * @param symbols a collection of open and close contents ... + * @param {string} content a content for searching inside it ... + * @returns a collection of closed content ... + */ +function findClosedContents( + symbols = [ + { + openSymbol: '', + closeSymbol: '' + } + ], + content = '' +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + if ( + !isValidArg(content) || + !hasChildArray(symbols) + ) { + return []; + } + + // + symbols.forEach(symbol => { + // + const closedContent = findClosedContent( + symbol.openSymbol, + symbol.closeSymbol, + content + ); + + // + if (hasChildArray(closedContent)) { + result.push( + ...closedContent + ); + } + }); + + // + return result; +} + +/** + * find all string content closed items ... + * + * @param {string} content a content which going to search ... + * @returns a collection of index descriptors ... + */ +function findClosedStrings(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // there are 3 types of strings ... + // ' " and ` + + // + const token1 = '\''; + const token1Stack = [0]; + token1Stack.pop(); + + // + const token2 = '"'; + const token2Stack = [0]; + token2Stack.pop(); + + // + const token3 = '`'; + const token3Stack = [0]; + token3Stack.pop(); + + // + const result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + for (let i = 0; i < content.length; i++) { + // + const currentChart = content.charAt(i); + + // + //#region Token 1 ... + if (currentChart === token1) { + // + if (!hasChildArray(token1Stack)) { + token1Stack.push(i); + } else { + // + const start = token1Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 2 ... + if (currentChart === token2) { + // + if (!hasChildArray(token2Stack)) { + token2Stack.push(i); + } else { + // + const start = token2Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 3 ... + if (currentChart === token3) { + // + if (!hasChildArray(token3Stack)) { + token3Stack.push(i); + } else { + // + const start = token3Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + } + + // + return result; +} + +/** + * find container indexes from within indexes ... + * + * @param {...{start: number, end: number}} index the collection of indexes to find beiggers inside ... + * @returns + */ +function findContainerIndexes(...index) { + // + let result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + let concatedIndexes = []; + for (let idx of index) { + // + // Index Childs ... + for (let iix of idx) { + // + // Check idx is standard ... + if ( + !iix || + !iix.end || + !iix.start || + iix.start > iix.end + ) { + continue; + } + + // + // Check index inside another index ... + concatedIndexes.push(iix); + } + } + + // + if (!hasChildArray(concatedIndexes)) { + return result; + } + + // + for (let ccIdx of concatedIndexes) { + // + const isInside = isIndexInside(ccIdx, ...concatedIndexes); + if (isInside) { + continue; + } + + // + if (hasChildArray(result)) { + // + const isInsideResult = isIndexInside(ccIdx, ...result); + if (isInsideResult) { + continue; + } + } + + // + result.push(ccIdx); + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds1( + tokens, + content, +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Extract token Indexes ... + const tokensIndexes = findAllIndexes(tokens, content); + if (!hasChildArray(tokensIndexes)) { + return []; + } + + // + // Extract Closed Objects Indexes ... + const closedArrays = findClosedContent('[', ']', content); + const closedObjects = findClosedContent('{', '}', content); + const closedStrings = findClosedStrings(content); + if ( + !hasChildArray(closedObjects) && + !hasChildArray(closedArrays) && + !hasChildArray(closedStrings) + ) { + return tokensIndexes; + } + + // + // find bigger sloded ... + let containerClosedItems = findContainerIndexes( + closedArrays, + closedObjects, + closedStrings + ).filter(i => !isSurroundedString(i.content)); + + // + let result = [-1]; + result.pop(); + + // + for (let tIdx of tokensIndexes) { + // + let canAdd = true; + for (let ccIndex of containerClosedItems) { + // + canAdd = isInsideIndex(tIdx, ccIndex); + if (canAdd) { + break; + } + } + + // + if (!canAdd) { + result.push(tIdx); + } + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds( + tokens, + content, +) { + // + // Define Result ... + let result = [-1]; + result.pop(); + + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Normalize Tokens ... + const normalizeTokens = toNormalArray(tokens); + if (!hasChildArray(normalizeTokens)) { + return result; + } + + // + // Extract Closed Objects Indexes ... + let openSymbols = [ + '{', + '[', + '\'', + '"', + '`' + ]; + let closeSymbols = [ + '}', + ']', + '\'', + '"', + '`' + ]; + let openStack = []; + let lastOpenSymbol = ''; + let lastClosedIndex = -1; + for (let i = 0; i < content.length; i++) { + // + const prevChar = content.charAt(i - 1) || ''; + const char = content.charAt(i); + const nextChar = content.charAt(i + 1) || ''; + + // + const isToken = normalizeTokens.includes(char); + const isOpenSymbol = openSymbols.includes(char); + const isCloseSymbol = closeSymbols.includes(char); + + // + if (isOpenSymbol && lastOpenSymbol !== char) { + openStack.push(i); + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? char : lastOpenSymbol; + } else if (isCloseSymbol) { + // + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? '' : lastOpenSymbol; + let lastPop = openStack.pop(); + if (openStack.length === 0) { + lastClosedIndex = lastPop; + } + } else if (isToken) { + if ( + i > lastClosedIndex && + openStack.length === 0 + ) { + result.push(i); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Validator Actions ... +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + * @returns {boolean} + */ +function isValidURL(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + const pattern = new RegExp( + '^([a-zA-Z]+:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', // fragment locator + 'i' + ); + + // + const result = pattern.test(value); + return result; +} + +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + */ +function isValidEmail(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + // + const pattern = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/gim; + + // + const result = pattern.test(value); + return result; +} +//#endregion + +// +//#region Normallizers ... +/** + * normallize an string ... + * + * @param {string} value specified value ... + * @returns {string} + */ +function toNormalString(value = "") { + // + if (!XTypeTools.isString(value)) { + value = ""; + } + + // + const result = value + .trim() + .toLowerCase(); + + // + return result; +} +//#endregion + +// +//#region Beautifiers ... +/** + * converts an object to string based on json and beautify result ... + * + * @param {any} object + * @returns {string} + */ +function beautifyJSON(object = undefined) { + // + // TODO: Complete this ... + let result = ""; + + // + // validate object ... + if (object === undefined) { + return result; + } + + // + // Convert result ... + result = JSON.stringify( + object, + null, + 4 + ); + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + endsWidth, + surroundBy, + isValidArg, + isValidArgs, + toNormalArray, + hasChildArray, + toStringExpression, + + // + sliceContent, + clearContent, + clearSurround, + clearArraySurround, + clearObjectSurround, + + // + isSurrounded, + isIndexInside, + isInsideIndex, + isKeyValueType, + isSurroundedArray, + isSurroundedString, + isSurroundedObject, + + // + findNearest, + findAllIndexes, + findCloseIndex, + findNearestIndex, + findClosedContent, + findClosedStrings, + findClosedContents, + findAllIndexesOutOfCloseds, + + // + // Validator Actions ... + isValidURL, + isValidEmail, + + // + // Normallizers ... + toNormalString, + + // + beautifyJSON, +} +//#endregion \ No newline at end of file diff --git a/Experts/x-strategies.ea.mq5 b/Experts/x-strategies.ea.mq5 new file mode 100644 index 00000000..c586ddeb --- /dev/null +++ b/Experts/x-strategies.ea.mq5 @@ -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 // + ); +} + +// \ No newline at end of file diff --git a/Experts/x-test-strategies.ea.mq5 b/Experts/x-test-strategies.ea.mq5 index 0c7e3800..11de2168 100644 --- a/Experts/x-test-strategies.ea.mq5 +++ b/Experts/x-test-strategies.ea.mq5 @@ -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; - // } } // diff --git a/Helpers/x-saherelm.xchvwap.helper.mq5 b/Helpers/x-saherelm.xchvwap.helper.mq5 new file mode 100644 index 00000000..d2b1e26c --- /dev/null +++ b/Helpers/x-saherelm.xchvwap.helper.mq5 @@ -0,0 +1,2608 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXCHVWAPHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// 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 "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XCHVWAP_BUFFERS +{ + // + XCHVWAP_S_LINE = 0, + XCHVWAP_S_STATE_LINE = 10, + // + XCHVWAP_M_LINE = 2, + XCHVWAP_M_STATE_LINE = 11, + // + XCHVWAP_L_LINE = 4, + XCHVWAP_L_STATE_LINE = 12, + // + XCHVWAP_H_LINE = 6, + XCHVWAP_H_STATE_LINE = 13, +}; + +// +enum ENUM_XCHVWAP_STATES +{ + // + XCHVWAP_BULLISH_STATE = 1, + XCHVWAP_BEARISH_STATE = 2, + XCHVWAP_NEUTURAL_STATE = 3, +}; + +// +// Input Models ... +struct XCHVWAPInputs +{ + // + // Props ... + + // + // Market ... + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Cycles ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Presentation ... + bool showShort; // Show Short Cycle + bool showMedium; // Show Medium Cycle + bool showLong; // Show Long Cycle + bool showHind; // Show Hind Cycle + + // + // Constructor(s) ... + XCHVWAPInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + appliedTo = PRICE_CLOSE; + + // + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + showShort = false; + showMedium = false; + showLong = false; + showHind = false; + } + + // + // Default ... + void Default() + { + // + appliedTo = PRICE_CLOSE; + + // + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + showShort = true; + showMedium = true; + showLong = true; + showHind = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = + // + MathMax(0, 0) + // + ; + + // + return result; + } +}; + +// +// Define Conditions ... +struct XCHVWAPConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + // Short ... + double s[]; + double sState[]; + + // + // Medium ... + double m[]; + double mState[]; + + // + // Long ... + double l[]; + double lState[]; + + // + // Hind ... + double h[]; + double hState[]; + + // + // Conditions ... + // + // Power ... + bool hasBullishPower; + bool hasBearishPower; + bool isBullishPowerUp; + bool isBearishPowerUp; + bool isBullishPowerIncreasing; + bool isBullishPowerDecreasing; + bool isBearishPowerIncreasing; + bool isBearishPowerDecreasing; + + // + // Short ... + bool isSBullish; + bool isSBearish; + bool isSSwitchedToBullish; + bool isSSwitchedToBearish; + + // + // Medium ... + bool isMBullish; + bool isMBearish; + bool isMSwitchedToBullish; + bool isMSwitchedToBearish; + + // + // Long ... + bool isLBullish; + bool isLBearish; + bool isLSwitchedToBullish; + bool isLSwitchedToBearish; + + // + // Hind ... + bool isHBullish; + bool isHBearish; + bool isHSwitchedToBullish; + bool isHSwitchedToBearish; + + // + void Clean() + { + // + Clean(s); + Clean(sState); + Clean(m); + Clean(mState); + Clean(l); + Clean(lState); + Clean(h); + Clean(hState); + + // + ArraySetAsSeries(s, true); + ArraySetAsSeries(sState, true); + ArraySetAsSeries(m, true); + ArraySetAsSeries(mState, true); + ArraySetAsSeries(l, true); + ArraySetAsSeries(lState, true); + ArraySetAsSeries(h, true); + ArraySetAsSeries(hState, true); + + // + // Conditions ... + + // + // Power ... + hasBullishPower = false; + hasBearishPower = false; + isBullishPowerUp = false; + isBearishPowerUp = false; + isBullishPowerIncreasing = false; + isBullishPowerDecreasing = false; + isBearishPowerIncreasing = false; + isBearishPowerDecreasing = false; + + // + // Short ... + isSBullish = false; + isSBearish = false; + isSSwitchedToBullish = false; + isSSwitchedToBearish = false; + + // + // Medium ... + isMBullish = false; + isMBearish = false; + isMSwitchedToBullish = false; + isMSwitchedToBearish = false; + + // + // Long ... + isLBullish = false; + isLBearish = false; + isLSwitchedToBullish = false; + isLSwitchedToBearish = false; + + // + // Hind ... + isHBullish = false; + isHBearish = false; + isHSwitchedToBullish = false; + isHSwitchedToBearish = false; + } + + // + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // Since We have to Use this + // Only for Filtering Signals ... + // We Can Ignore Scoring ... + // or Complete this later ... + + // + // Conditions ... + + // + // Power ... + if (hasBullishPower) + { + bullishScore++; + } + if (hasBearishPower) + { + bearishScore++; + } + if (isBullishPowerUp) + { + bullishScore++; + } + if (isBearishPowerUp) + { + bearishScore++; + } + if (isBullishPowerIncreasing) + { + bullishScore++; + } + if (isBullishPowerDecreasing) + { + bearishScore++; + } + if (isBearishPowerIncreasing) + { + bearishScore++; + } + if (isBearishPowerDecreasing) + { + bullishScore++; + } + + // + // Short ... + if (isSBullish) + { + bullishScore++; + } + if (isSBearish) + { + bearishScore++; + } + if (isSSwitchedToBullish) + { + bullishScore++; + } + if (isSSwitchedToBearish) + { + bearishScore++; + } + + // + // Medium ... + if (isMBullish) + { + bullishScore++; + } + if (isMBearish) + { + bearishScore++; + } + if (isMSwitchedToBullish) + { + bullishScore++; + } + if (isMSwitchedToBearish) + { + bearishScore++; + } + + // + // Long ... + if (isLBullish) + { + bullishScore++; + } + if (isLBearish) + { + bearishScore++; + } + if (isLSwitchedToBullish) + { + bullishScore++; + } + if (isLSwitchedToBearish) + { + bearishScore++; + } + + // + // Hind ... + if (isHBullish) + { + bullishScore++; + } + if (isHBearish) + { + bearishScore++; + } + if (isHSwitchedToBullish) + { + bullishScore++; + } + if (isHSwitchedToBearish) + { + bearishScore++; + } + } + + // + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + // Power ... + ToString("hasBullishPower", hasBullishPower, ignoreFalseConditions, separator) + + ToString("hasBearishPower", hasBearishPower, ignoreFalseConditions, separator) + + ToString("isBullishPowerUp", isBullishPowerUp, ignoreFalseConditions, separator) + + ToString("isBearishPowerUp", isBearishPowerUp, ignoreFalseConditions, separator) + + ToString("isBullishPowerIncreasing", isBullishPowerIncreasing, ignoreFalseConditions, separator) + + ToString("isBullishPowerDecreasing", isBullishPowerDecreasing, ignoreFalseConditions, separator) + + ToString("isBearishPowerIncreasing", isBearishPowerIncreasing, ignoreFalseConditions, separator) + + ToString("isBearishPowerDecreasing", isBearishPowerDecreasing, ignoreFalseConditions, separator) + + // + // Short ... + ToString("isSBullish", isSBullish, ignoreFalseConditions, separator) + + ToString("isSBearish", isSBearish, ignoreFalseConditions, separator) + + ToString("isSSwitchedToBullish", isSSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSSwitchedToBearish", isSSwitchedToBearish, ignoreFalseConditions, separator) + + // + // Medium ... + ToString("isMBullish", isMBullish, ignoreFalseConditions, separator) + + ToString("isMBearish", isMBearish, ignoreFalseConditions, separator) + + ToString("isMSwitchedToBullish", isMSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMSwitchedToBearish", isMSwitchedToBearish, ignoreFalseConditions, separator) + + // + // Long ... + ToString("isLBullish", isLBullish, ignoreFalseConditions, separator) + + ToString("isLBearish", isLBearish, ignoreFalseConditions, separator) + + ToString("isLSwitchedToBullish", isLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLSwitchedToBearish", isLSwitchedToBearish, ignoreFalseConditions, separator) + + // + // Hind ... + ToString("isHBullish", isHBullish, ignoreFalseConditions, separator) + + ToString("isHBearish", isHBearish, ignoreFalseConditions, separator) + + ToString("isHSwitchedToBullish", isHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHSwitchedToBearish", isHSwitchedToBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + // + string GetTag() + { + return "XCHVWAP"; + } +}; + +// +// Class ... +class XSCXCHVWAPHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXCHVWAPHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXCHVWAPHelper() + { + // + Clean(sBuffer); + Clean(sStateBuffer); + Clean(mBuffer); + Clean(mStateBuffer); + Clean(lBuffer); + Clean(lStateBuffer); + Clean(hBuffer); + Clean(hStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCHVWAPInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(sBuffer, true); + ArraySetAsSeries(sStateBuffer, true); + ArraySetAsSeries(mBuffer, true); + ArraySetAsSeries(mStateBuffer, true); + ArraySetAsSeries(lBuffer, true); + ArraySetAsSeries(lStateBuffer, true); + ArraySetAsSeries(hBuffer, true); + ArraySetAsSeries(hStateBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xchvwap", + // + // Inputs ... + // + // Market ... + "", + mInputs.appliedTo, + // + // Cycles ... + "", + // + // Short ... + "", + mInputs.scMethod, + mInputs.scPeriod, + // + // Medium ... + "", + mInputs.mcMethod, + mInputs.mcPeriod, + // + // Long ... + "", + mInputs.lcMethod, + mInputs.lcPeriod, + // + // Hind ... + "", + mInputs.hcMethod, + mInputs.hcPeriod, + // + // Presentation ... + "", + mInputs.showShort, + mInputs.showMedium, + mInputs.showLong, + mInputs.showHind + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XCHVWAPInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCHVWAPInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Short ... + + // + double GetS( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return sBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyS( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + sBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return sStateBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + sStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Medium ... + + // + double GetM( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return mBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyM( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mBuffer, + buffer, + forceClean + // + ); + } + + // + double GetMState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return mStateBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyMState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Long ... + + // + double GetL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return lBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lBuffer, + buffer, + forceClean + // + ); + } + + // + double GetLState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return lStateBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyLState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Hind ... + + // + double GetH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return hBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hBuffer, + buffer, + forceClean + // + ); + } + + // + double GetHState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return hStateBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyHState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + ENUM_XCHVWAP_STATES ToState(double value) + { + // + ENUM_XCHVWAP_STATES result = value == 1 + ? XCHVWAP_BULLISH_STATE + : value == 2 + ? XCHVWAP_BEARISH_STATE + : XCHVWAP_NEUTURAL_STATE; + + // + return result; + } + + // + bool IsBullish(double value) + { + // + bool result = false; + + // + result = + // + ToState(value) == XCHVWAP_BULLISH_STATE; + // + ; + + // + return result; + } + + // + bool IsBearish(double value) + { + // + bool result = false; + + // + result = + // + ToState(value) == XCHVWAP_BEARISH_STATE; + // + ; + + // + return result; + } + + // + int GetValues( + int barIndex, // Bar Index + double &values[] // Result + ) + { + // + int result = 0; + + // + Clean(values); + + // + ENUM_X_MARKET_CYCLES cycles[]; + int cyclesCount = GetAllMarketCycles(cycles); + if (!IsValidSize(cyclesCount)) + { + return result; + } + + // + for (int i = 0; i < cyclesCount; i++) + { + // + double iValue = GetCycleValue( + barIndex, + cycles[i] // + ); + + // + Add( + iValue, + values // + ); + } + + // + result = ArraySize(values); + + // + return result; + } + + // + double GetCycleValue( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES cycle // Cycle + ) + { + // + double result = 0; + + // + switch (cycle) + { + // + // SHORT ... + case X_MARKET_CYCLE_SHORT: + result = GetS(barIndex); + break; + + // + // MEDIUM ... + case X_MARKET_CYCLE_MEDIUM: + result = GetM(barIndex); + break; + + // + // LONG ... + case X_MARKET_CYCLE_LONG: + result = GetL(barIndex); + break; + + // + // HIND ... + case X_MARKET_CYCLE_HIND: + result = GetH(barIndex); + break; + } + + // + return result; + } + + // + double GetCycleState( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES cycle // Cycle + ) + { + // + double result = 0; + + // + switch (cycle) + { + // + // SHORT ... + case X_MARKET_CYCLE_SHORT: + result = GetSState(barIndex); + break; + + // + // MEDIUM ... + case X_MARKET_CYCLE_MEDIUM: + result = GetMState(barIndex); + break; + + // + // LONG ... + case X_MARKET_CYCLE_LONG: + result = GetLState(barIndex); + break; + + // + // HIND ... + case X_MARKET_CYCLE_HIND: + result = GetHState(barIndex); + break; + } + + // + return result; + } + + // + int GetBullishCycles( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // Result + ) + { + // + int result = 0; + + // + Clean(cycles); + + // + ENUM_X_MARKET_CYCLES allCycles[]; + int allCyclesCount = GetAllMarketCycles(allCycles); + if (!IsValidSize(allCyclesCount)) + { + return result; + } + + // + for (int i = 0; i < allCyclesCount; i++) + { + // + double cState = GetCycleState( + barIndex, + allCycles[i] // + ); + + // + if (IsBullish(cState)) + { + // + Add( + allCycles[i], + cycles // + ); + } + } + + // + result = ArraySize(cycles); + + // + return result; + } + + // + int GetBearishCycles( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // Result + ) + { + // + int result = 0; + + // + Clean(cycles); + + // + ENUM_X_MARKET_CYCLES allCycles[]; + int allCyclesCount = GetAllMarketCycles(allCycles); + if (!IsValidSize(allCyclesCount)) + { + return result; + } + + // + for (int i = 0; i < allCyclesCount; i++) + { + // + double cState = GetCycleState( + barIndex, + allCycles[i] // + ); + + // + if (IsBearish(cState)) + { + // + Add( + allCycles[i], + cycles // + ); + } + } + + // + result = ArraySize(cycles); + + // + return result; + } + + // + int GetCyclesValues( + int barIndex, // Bar Index + double &values[], // Values + ENUM_X_MARKET_CYCLES &cycles[] // Cycles + ) + { + // + int result = 0; + + // + Clean(values); + + // + int count = ArraySize(cycles); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + double iValue = GetCycleValue( + barIndex, + cycles[i] // + ); + + // + Add( + iValue, + values // + ); + } + + // + result = ArraySize(values); + + // + return result; + } + + // + int GetBullishCyclesValues( + int barIndex, // Bar Index + double &values[] // Values + ) + { + // + int result = 0; + + // + Clean(values); + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetBullishCycles( + barIndex, + cycles // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetCyclesValues( + barIndex, + values, + cycles // + ); + + // + return result; + } + + // + int GetBearishCyclesValues( + int barIndex, // Bar Index + double &values[] // Values + ) + { + // + int result = 0; + + // + Clean(values); + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetBearishCycles( + barIndex, + cycles // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetCyclesValues( + barIndex, + values, + cycles // + ); + + // + return result; + } + + // + double GetCyclesMax( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // Cycles + ) + { + // + double result = 0; + + // + double values[]; + int count = GetCyclesValues( + barIndex, + values, + cycles // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetSpecifiedMax(values); + + // + return result; + } + + // + double GetCyclesMin( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // Cycles + ) + { + // + double result = 0; + + // + double values[]; + int count = GetCyclesValues( + barIndex, + values, + cycles // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetSpecifiedMin(values); + + // + return result; + } + + // + double GetMax( + int barIndex // Bar Index + ) + { + // + double result = 0; + + // + double values[]; + int valuesCount = GetValues( + barIndex, + values // + ); + if (!IsValidSize(valuesCount)) + { + return result; + } + + // + result = GetSpecifiedMax(values); + + // + return result; + } + + // + double GetMin( + int barIndex // Bar Index + ) + { + // + double result = 0; + + // + double values[]; + int valuesCount = GetValues( + barIndex, + values // + ); + if (!IsValidSize(valuesCount)) + { + return result; + } + + // + result = GetSpecifiedMin(values); + + // + return result; + } + + // + double GetBullishPower( + int barIndex // Bar Index + ) + { + // + double result = 0; + + // + double values[]; + int count = GetBullishCyclesValues( + barIndex, + values // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = MathAbs(GetSum(values)); + + // + return result; + } + + // + double GetBearishPower( + int barIndex // Bar Index + ) + { + // + double result = 0; + + // + double values[]; + int count = GetBearishCyclesValues( + barIndex, + values // + ); + if (!IsValidSize(count)) + { + return result; + } + + // + result = MathAbs(GetSum(values)); + + // + return result; + } + + // + double GetCyclesBullishPower( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // + ) + { + // + double result = 0; + + // + int cyclesCount = ArraySize(cycles); + if (!IsValidSize(cyclesCount)) + { + return result; + } + + // + for (int i = 0; i < cyclesCount; i++) + { + // + double power = GetCycleValue( + barIndex, + cycles[i] // + ); + + // + if (IsBullish(power)) + { + result += MathAbs(power); + } + } + + // + return result; + } + + // + double GetCyclesBearishPower( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // + ) + { + // + double result = 0; + + // + int cyclesCount = ArraySize(cycles); + if (!IsValidSize(cyclesCount)) + { + return result; + } + + // + for (int i = 0; i < cyclesCount; i++) + { + // + double power = GetCycleValue( + barIndex, + cycles[i] // + ); + + // + if (IsBearish(power)) + { + result += MathAbs(power); + } + } + + // + return result; + } + + // + bool HasBullishPower( + int barIndex // Bar Index + ) + { + // + bool result = false; + + // + double bullishPower = GetBullishPower(barIndex); + double bearishPower = GetBearishPower(barIndex); + + // + result = + // + bearishPower >= 0 && + bullishPower > bearishPower + // + ; + + // + return result; + } + + // + bool HasBearishPower( + int barIndex // Bar Index + ) + { + // + bool result = false; + + // + double bullishPower = GetBullishPower(barIndex); + double bearishPower = GetBearishPower(barIndex); + + // + result = + // + bullishPower >= 0 && + bearishPower > bullishPower + // + ; + + // + return result; + } + + // + bool HasCyclesBullishPower( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // + ) + { + // + bool result = false; + + // + double bullishPower = GetCyclesBullishPower(barIndex, cycles); + double bearishPower = GetCyclesBearishPower(barIndex, cycles); + + // + result = + // + bearishPower >= 0 && + bullishPower > bearishPower + // + ; + + // + return result; + } + + // + bool HasCyclesBearishPower( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[] // + ) + { + // + bool result = false; + + // + double bullishPower = GetCyclesBullishPower(barIndex, cycles); + double bearishPower = GetCyclesBearishPower(barIndex, cycles); + + // + result = + // + bullishPower >= 0 && + bearishPower > bullishPower + // + ; + + // + return result; + } + + // + // Check Bullish Power Increasing ... + bool IsBullishPowerIncreasing( + int barIndex, // Bar Index + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetBullishPower(barIndex); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetBullishPower(i); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower > iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower > lastPower + // + ; + } + + // + return result; + } + + // + // Check Bullish Power Decreasing ... + bool IsBullishPowerDecreasing( + int barIndex, // Bar Index + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetBullishPower(barIndex); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetBullishPower(i); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower < iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower < lastPower + // + ; + } + + // + return result; + } + + // + // Check Bearish Power Increasing ... + bool IsBearishPowerIncreasing( + int barIndex, // Bar Index + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetBearishPower(barIndex); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetBearishPower(i); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower > iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower > lastPower + // + ; + } + + // + return result; + } + + // + // Check Bearish Power Decreasing ... + bool IsBearishPowerDecreasing( + int barIndex, // Bar Index + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetBearishPower(barIndex); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetBearishPower(i); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower < iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower < lastPower + // + ; + } + + // + return result; + } + + // + // Check Bullish Power Increasing ... + bool IsCyclesBullishPowerIncreasing( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[], // + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetCyclesBullishPower(barIndex, cycles); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetCyclesBullishPower(i, cycles); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower > iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower > lastPower + // + ; + } + + // + return result; + } + + // + // Check Bullish Power Decreasing ... + bool IsCyclesBullishPowerDecreasing( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[], // + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetCyclesBullishPower(barIndex, cycles); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetCyclesBullishPower(i, cycles); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower < iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower < lastPower + // + ; + } + + // + return result; + } + + // + // Check Bearish Power Increasing ... + bool IsCyclesBearishPowerIncreasing( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[], // + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetCyclesBearishPower(barIndex, cycles); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetCyclesBearishPower(i, cycles); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower > iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower > lastPower + // + ; + } + + // + return result; + } + + // + // Check Bearish Power Decreasing ... + bool IsCyclesBearishPowerDecreasing( + int barIndex, // Bar Index + ENUM_X_MARKET_CYCLES &cycles[], // + int loopback = 5 // Loopback + ) + { + // + bool result = false; + + // + if (loopback <= 0) + { + loopback = 5; + } + + // + double firstPower = GetCyclesBearishPower(barIndex, cycles); + double lastPower = firstPower; + for (int i = barIndex + 1; i < barIndex + loopback; i++) + { + // + double iPower = GetCyclesBearishPower(i, cycles); + + // + result = + // + iPower > 0 && + firstPower > 0 && + lastPower < iPower + // + ; + if (!result) + { + break; + } + + // + lastPower = iPower; + } + + // + if (result) + { + // + result = + // + firstPower < lastPower + // + ; + } + + // + return result; + } + + // + // Conditions ... + + // + bool GetConditions( + XCHVWAPConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + // Buffers ... + + // + // Short ... + CopyS( + zIndex, + loopback, + conditions.s // + ); + CopySState( + zIndex, + loopback, + conditions.sState // + ); + + // + // Medium ... + CopyM( + zIndex, + loopback, + conditions.m // + ); + CopyMState( + zIndex, + loopback, + conditions.mState // + ); + + // + // Long ... + CopyL( + zIndex, + loopback, + conditions.l // + ); + CopyLState( + zIndex, + loopback, + conditions.lState // + ); + + // + // Hind ... + CopyH( + zIndex, + loopback, + conditions.h // + ); + CopyHState( + zIndex, + loopback, + conditions.hState // + ); + + // + // Conditions ... + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Power ... + + // + bool hasBullishPower = HasBullishPower(cIndex); + bool hasBullishPowerPrev = HasBullishPower(pIndex); + + // + bool hasBearishPower = HasBearishPower(cIndex); + bool hasBearishPowerPrev = HasBearishPower(pIndex); + + // + bool isBullishPowerUp = hasBullishPower && + !hasBullishPowerPrev; + bool isBearishPowerUp = hasBearishPower && + !hasBearishPowerPrev; + + // + bool isBullishPowerIncreasing = IsBullishPowerIncreasing(cIndex); + bool isBullishPowerDecreasing = IsBullishPowerDecreasing(cIndex); + bool isBearishPowerIncreasing = IsBearishPowerIncreasing(cIndex); + bool isBearishPowerDecreasing = IsBearishPowerDecreasing(cIndex); + + // + conditions.hasBullishPower = hasBullishPower; + conditions.hasBearishPower = hasBearishPower; + conditions.isBullishPowerUp = isBullishPowerUp; + conditions.isBearishPowerUp = isBearishPowerUp; + conditions.isBullishPowerIncreasing = isBullishPowerIncreasing; + conditions.isBullishPowerDecreasing = isBullishPowerDecreasing; + conditions.isBearishPowerIncreasing = isBearishPowerIncreasing; + conditions.isBearishPowerDecreasing = isBearishPowerDecreasing; + + // + // Short ... + + // + bool isSBullish = IsBullish(conditions.sState[cIndex]); + bool isSBullishPrev = IsBullish(conditions.sState[pIndex]); + + // + bool isSBearish = IsBearish(conditions.sState[cIndex]); + bool isSBearishPrev = IsBearish(conditions.sState[pIndex]); + + // + bool isSSwitchedToBullish = isSBullish && + !isSBullishPrev; + bool isSSwitchedToBearish = isSBearish && + !isSBearishPrev; + + // + conditions.isSBullish = isSBullish; + conditions.isSBearish = isSBearish; + conditions.isSSwitchedToBullish = isSSwitchedToBullish; + conditions.isSSwitchedToBearish = isSSwitchedToBearish; + + // + // Medium ... + + // + bool isMBullish = IsBullish(conditions.mState[cIndex]); + bool isMBullishPrev = IsBullish(conditions.mState[pIndex]); + + // + bool isMBearish = IsBearish(conditions.mState[cIndex]); + bool isMBearishPrev = IsBearish(conditions.mState[pIndex]); + + // + bool isMSwitchedToBullish = isMBullish && + !isMBullishPrev; + bool isMSwitchedToBearish = isMBearish && + !isMBearishPrev; + + // + conditions.isMBullish = isMBullish; + conditions.isMBearish = isMBearish; + conditions.isMSwitchedToBullish = isMSwitchedToBullish; + conditions.isMSwitchedToBearish = isMSwitchedToBearish; + + // + // Long ... + + // + bool isLBullish = IsBullish(conditions.lState[cIndex]); + bool isLBullishPrev = IsBullish(conditions.lState[pIndex]); + + // + bool isLBearish = IsBearish(conditions.lState[cIndex]); + bool isLBearishPrev = IsBearish(conditions.lState[pIndex]); + + // + bool isLSwitchedToBullish = isLBullish && + !isLBullishPrev; + bool isLSwitchedToBearish = isLBearish && + !isLBearishPrev; + + // + conditions.isLBullish = isLBullish; + conditions.isLBearish = isLBearish; + conditions.isLSwitchedToBullish = isLSwitchedToBullish; + conditions.isLSwitchedToBearish = isLSwitchedToBearish; + + // + // Hind ... + + // + bool isHBullish = IsBullish(conditions.hState[cIndex]); + bool isHBullishPrev = IsBullish(conditions.hState[pIndex]); + + // + bool isHBearish = IsBearish(conditions.hState[cIndex]); + bool isHBearishPrev = IsBearish(conditions.hState[pIndex]); + + // + bool isHSwitchedToBullish = isHBullish && + !isHBullishPrev; + bool isHSwitchedToBearish = isHBearish && + !isHBearishPrev; + + // + conditions.isHBullish = isHBullish; + conditions.isHBearish = isHBearish; + conditions.isHSwitchedToBullish = isHSwitchedToBullish; + conditions.isHSwitchedToBearish = isHSwitchedToBearish; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XCHVWAPInputs mInputs; // Inputs ... + + // + // Buffers ... + + // + // Short ... + double sBuffer[]; + double sStateBuffer[]; + + // + // Medium ... + double mBuffer[]; + double mStateBuffer[]; + + // + // Long ... + double lBuffer[]; + double lStateBuffer[]; + + // + // Hind ... + double hBuffer[]; + double hStateBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Short ... + CopyBuffer( + mHandler, + XCHVWAP_S_LINE, + 0, + totalBars, + sBuffer + // + ); + CopyBuffer( + mHandler, + XCHVWAP_S_STATE_LINE, + 0, + totalBars, + sStateBuffer + // + ); + + // + // Medium ... + CopyBuffer( + mHandler, + XCHVWAP_M_LINE, + 0, + totalBars, + mBuffer + // + ); + CopyBuffer( + mHandler, + XCHVWAP_M_STATE_LINE, + 0, + totalBars, + mStateBuffer + // + ); + + // + // Long ... + CopyBuffer( + mHandler, + XCHVWAP_L_LINE, + 0, + totalBars, + lBuffer + // + ); + CopyBuffer( + mHandler, + XCHVWAP_L_STATE_LINE, + 0, + totalBars, + lStateBuffer + // + ); + + // + // Hind ... + CopyBuffer( + mHandler, + XCHVWAP_H_LINE, + 0, + totalBars, + hBuffer + // + ); + CopyBuffer( + mHandler, + XCHVWAP_H_STATE_LINE, + 0, + totalBars, + hStateBuffer + // + ); + }; +}; + +// \ No newline at end of file diff --git a/Indicators/x-saherelm.xchvwap.mq5 b/Indicators/x-saherelm.xchvwap.mq5 new file mode 100644 index 00000000..14d99bda --- /dev/null +++ b/Indicators/x-saherelm.xchvwap.mq5 @@ -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; + } +} + +// \ No newline at end of file diff --git a/Parsers/x-saherelm.xch.parser.mq5 b/Parsers/x-saherelm.xch.parser.mq5 index 1946e874..8ef4b959 100644 --- a/Parsers/x-saherelm.xch.parser.mq5 +++ b/Parsers/x-saherelm.xch.parser.mq5 @@ -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" + ")"; // diff --git a/Strategies/x-saherelm.xch.strategy.mq5 b/Strategies/x-saherelm.xch.strategy.mq5 index 1b8822f8..640c4379 100644 --- a/Strategies/x-saherelm.xch.strategy.mq5 +++ b/Strategies/x-saherelm.xch.strategy.mq5 @@ -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 // + ); } // diff --git a/Test/x-saherelm.test.setup.mq5 b/Test/x-saherelm.test.setup.mq5 deleted file mode 100644 index 8e7b6dfa..00000000 --- a/Test/x-saherelm.test.setup.mq5 +++ /dev/null @@ -1,1779 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Class Library -// ---------------------------------------------- -// Name: XTestSetup -// Description: provides implementation of Test -// Setup ... -// -// -// 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 "../Libraries/x-saherelm.xtrade.lib.mq5" -#include "../Classes/x-saherelm.xalert.class.mq5" - -// -#include "../Helpers/x-saherelm.xrl.helper.mq5" -#include "../Helpers/x-saherelm.xmc.helper.mq5" -#include "../Helpers/x-saherelm.xpv.helper.mq5" -#include "../Helpers/x-saherelm.xtd.helper.mq5" -#include "../Helpers/x-saherelm.xhk.helper.mq5" -#include "../Helpers/x-saherelm.xsln.helper.mq5" -#include "../Helpers/x-saherelm.xstr.helper.mq5" -#include "../Helpers/x-saherelm.xche.helper.mq5" -#include "../Helpers/x-saherelm.xich.helper.mq5" -#include "../Helpers/x-saherelm.xmrb.helper.mq5" -#include "../Helpers/x-saherelm.xosc.helper.mq5" -#include "../Helpers/x-saherelm.xvlm.helper.mq5" -#include "../Helpers/x-saherelm.xhtd.helper.mq5" -#include "../Helpers/x-saherelm.xchma.helper.mq5" -#include "../Helpers/x-saherelm.xatsl.helper.mq5" -#include "../Helpers/x-saherelm.xdmnt.helper.mq5" -#include "../Helpers/x-saherelm.xasct.helper.mq5" -#include "../Helpers/x-saherelm.xsslc.helper.mq5" -#include "../Helpers/x-saherelm.xhull.helper.mq5" -#include "../Helpers/x-saherelm.xadxtd.helper.mq5" - -// -struct XTestInputs -{ - // - // Props ... - - // - // Commons ... - string symbol; // Symbol - ENUM_TIMEFRAMES period; // Time Frame - - // - double volume; // - double tpPoint; // - double slPoint; // - - // - // Helpers Inputs ... - XRLInputs rlInputs; // XRL Inputs - XMCInputs mcInputs; // XMC Inputs - XPVInputs pvInputs; // XPV Inputs - XTDInputs tdInputs; // XTD Inputs - XHKInputs hkInputs; // XHK Inputs - XHTDInputs htdInputs; // XHTD Inputs - XCHEInputs cheInputs; // XCHE Inputs - XICHInputs ichInputs; // XICH Inputs - XSTRInputs strInputs; // XSTR Inputs - XMRBInputs mrbInputs; // XMRB Inputs - XOSCInputs oscInputs; // XOSC Inputs - XVLMInputs vlmInputs; // XVLM Inputs - XSLNInputs slnInputs; // XSLN Inputs - XCHMAInputs chmaInputs; // XCHMA Inputs - XATSLInputs atslInputs; // XATSL Inputs - XDMNTInputs dmntInputs; // XDMNT Inputs - XASCTInputs asctInputs; // XASCT Inputs - XSSLCInputs sslcInputs; // XSSLC Inputs - XHULLInputs hullInputs; // XHULL Inputs - XADXTDInputs adxtdInputs; // XADXTD Inputs - - // - // Constructor ... - XTestInputs() - { - Clean(); - } - - // - // Tools ... - // - bool Init() - { - // - Default(); - - // - bool result = IsValid(); - - // - return result; - } - bool Init( - string _symbol, // Symbol - ENUM_TIMEFRAMES _period, // Time Frame - XRLInputs &_rlInputs, // XRL Inputs - XMCInputs &_mcInputs, // XMC Inputs - XPVInputs &_pvInputs, // XPV Inputs - XTDInputs &_tdInputs, // XTD Inputs - XHKInputs &_hkInputs, // XHK Inputs - XHTDInputs &_htdInputs, // XHTD Inputs - XCHEInputs &_cheInputs, // XCHE Inputs - XICHInputs &_ichInputs, // XICH Inputs - XSTRInputs &_strInputs, // XSTR Inputs - XMRBInputs &_mrbInputs, // XMRB Inputs - XOSCInputs &_oscInputs, // XOSC Inputs - XVLMInputs &_vlmInputs, // XVLM Inputs - XSLNInputs &_slnInputs, // XSLN Inputs - XCHMAInputs &_chmaInputs, // XCHMA Inputs - XATSLInputs &_atslInputs, // XATSL Inputs - XDMNTInputs &_dmntInputs, // XDMNT Inputs - XASCTInputs &_asctInputs, // XASCT Inputs - XSSLCInputs &_sslcInputs, // XSSLC Inputs - XHULLInputs &_hullInputs, // XHULL Inputs - XADXTDInputs &_adxtdInputs // XADXTD Inputs - ) - { - // - this.symbol = _symbol; - this.period = _period; - - // - // Helpers Inputs ... - this.rlInputs = _rlInputs; - this.mcInputs = _mcInputs; - this.pvInputs = _pvInputs; - this.tdInputs = _tdInputs; - this.hkInputs = _hkInputs; - this.htdInputs = _htdInputs; - this.cheInputs = _cheInputs; - this.ichInputs = _ichInputs; - this.strInputs = _strInputs; - this.mrbInputs = _mrbInputs; - this.oscInputs = _oscInputs; - this.vlmInputs = _vlmInputs; - this.chmaInputs = _chmaInputs; - this.atslInputs = _atslInputs; - this.dmntInputs = _dmntInputs; - this.asctInputs = _asctInputs; - this.sslcInputs = _sslcInputs; - this.hullInputs = _hullInputs; - this.adxtdInputs = _adxtdInputs; - - // - bool result = IsValid(); - - // - return result; - } - - // - // Cleanup ... - void Clean() - { - // - symbol = NULL; - period = NULL; - - // - tpPoint = 0; - slPoint = 0; - - // - rlInputs.Clean(); - mcInputs.Clean(); - pvInputs.Clean(); - tdInputs.Clean(); - hkInputs.Clean(); - cheInputs.Clean(); - ichInputs.Clean(); - strInputs.Clean(); - mrbInputs.Clean(); - oscInputs.Clean(); - vlmInputs.Clean(); - slnInputs.Clean(); - htdInputs.Clean(); - chmaInputs.Clean(); - asctInputs.Clean(); - sslcInputs.Clean(); - hullInputs.Clean(); - atslInputs.Clean(); - dmntInputs.Clean(); - adxtdInputs.Clean(); - } - - // - // Default ... - void Default() - { - // - tpPoint = 0; - slPoint = 0; - - // - rlInputs.Default(); - mcInputs.Default(); - pvInputs.Default(); - tdInputs.Default(); - hkInputs.Default(); - cheInputs.Default(); - ichInputs.Default(); - strInputs.Default(); - mrbInputs.Default(); - oscInputs.Default(); - vlmInputs.Default(); - slnInputs.Default(); - htdInputs.Default(); - chmaInputs.Default(); - asctInputs.Default(); - sslcInputs.Default(); - hullInputs.Default(); - atslInputs.Default(); - dmntInputs.Default(); - adxtdInputs.Default(); - } - - // - // Validate ... - bool IsValid() - { - // - bool result = false; - - // - result = - // - IsValid(symbol) && - IsValid(period) - // - ; - if (!result) - { - return result; - } - - // - result = rlInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = chmaInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = tdInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = slnInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = pvInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = hkInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = cheInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = ichInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = strInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = mrbInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = oscInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = vlmInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = mcInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = asctInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = sslcInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = hullInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = adxtdInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = htdInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = atslInputs.IsValid(); - if (!result) - { - return result; - } - - // - result = dmntInputs.IsValid(); - if (!result) - { - return result; - } - - // - return result; - } -}; - -// -struct XTestConditions -{ - // - // Props ... - // - // Common ... - string symbol; - ENUM_TIMEFRAMES period; - datetime time; - - // - // Conditions ... - XRLConditions rlConditions; - XMCConditions mcConditions; - XPVConditions pvConditions; - XTDConditions tdConditions; - XHKConditions hkConditions; - XCHEConditions cheConditions; - XICHConditions ichConditions; - XSTRConditions strConditions; - XMRBConditions mrbConditions; - XVLMConditions vlmConditions; - XHTDConditions htdConditions; - XSLNConditions slnConditions; - XCHMAConditions chmaConditions; - XATSLConditions atslConditions; - XASCTConditions asctConditions; - XSSLCConditions sslcConditions; - XHULLConditions hullConditions; - XDMNTConditions dmntConditions; - XADXTDConditions adxtdConditions; - - // - // Oscillators ... - double cci[]; - double rsi[]; - double macd[]; - double macdSignal[]; - - // - // Signal ... - - // - // Conditions Provided Signal ... - XSignal signal; - - // - // Signal Verifications ... - int pushers; - - // - // Signal Providers .... - string providers[]; - - // - // Conditions Verifications ... - int longVerifications; - int shortVerifications; - - // - void CleanSignal() - { - // - signal.Clean(); - Clean(providers); - - // - pushers = 0; - longVerifications = 0; - shortVerifications = 0; - } - - // - // Generate Conditions Based Signals ... - bool GenerateSignal( - double &tp, - double &sl, - double volume, - double tpPoint, - double slPoint // - ) - { - // - bool result = false; - - // - bool hasLong = GenerateLongSignal( - tp, - sl, - volume, - tpPoint, - slPoint // - ); - if (hasLong) - { - // - result = hasLong; - return result; - } - - // - bool hasShort = GenerateShortSignal( - tp, - sl, - volume, - tpPoint, - slPoint // - ); - if (hasShort) - { - // - result = hasShort; - return result; - } - - // - return result; - } - - // - bool GenerateLongSignal( - double &tp, - double &sl, - double volume, - double tpPoint, - double slPoint // - ) - { - // - bool result = false; - - // - double mTP = 0; - double mSL = 0; - double mR2R = 1.5; - double mEntry = 0; - - // - ENUM_POSITION_TYPE mType = POSITION_TYPE_BUY; - ENUM_X_ORDER_MODES mMode = X_ORDER_MODE_MARKET; - - // - mEntry = GetEntry( - symbol, - mType // - ); - - // - // XATRL ... - bool long1 = - // - // Start Conditions ... - (rlConditions.isVerifierSwitchedToBullish && - rlConditions.isFastBullish && - rlConditions.isSlowBearish && - rlConditions.isFastOverSlow) - // - && - // - // Verifications ... - // XSTR ... - (strConditions.isTrendBullish || - strConditions.isTrendSwitchedToBullish) - // - && - // - // XATSL ... - (atslConditions.isBullish || - atslConditions.isSwitchedToBullish) - // - && - // - // XHTD ... - (htdConditions.isBullish || - htdConditions.isSwitchedToBullish) - // - && - // - // XVLM ... - (vlmConditions.isVolumeBullish || - vlmConditions.isVolumeChangedToBullish) - // - && - // - // XCHE ... - (cheConditions.isBullish || - cheConditions.isStrongBullish || - cheConditions.isSwitchedToBullish || - cheConditions.isStrongSwitchedToBullish) - // - && - // - // XHK ... - (hkConditions.isHKBullish || - hkConditions.isSMHKBullish || - hkConditions.isHKSwitchedToBullish || - hkConditions.isSMHKSwitchedToBullish) - // - ; - if (long1) - { - // - Add( - "XATRL", - providers // - ); - - // - pushers++; - - // - // Calculate TP and SL ... - - // - mSL = atslConditions.atsl[1]; - - // - double risk = MathAbs(mSL - mEntry); - double reward = risk * mR2R; - - // - mTP = mEntry + reward; - - // - tp = mTP; - sl = mSL; - } - - // - result = - // - long1 - // - ; - if (result) - { - // - result = signal.Prepare( - symbol, - "XATRL", - period, - mType, - mMode, - mEntry, - volume, - 0, // mSL, - mTP // - ); - // if (result) - // { - // // - // XSignal opposit; - // bool canSupport = signal.GenerateOpposit(opposit); - // if (canSupport) - // { - // // - // AddRef( - // opposit, - // signal.supports // - // ); - // } - // } - } - - // - return result; - } - - // - bool GenerateShortSignal( - double &tp, - double &sl, - double volume, - double tpPoint, - double slPoint // - ) - { - // - bool result = false; - - // - return result; - - // - double mTP = 0; - double mSL = 0; - double mR2R = 1.5; - double mEntry = 0; - - // - ENUM_POSITION_TYPE mType = POSITION_TYPE_SELL; - ENUM_X_ORDER_MODES mMode = X_ORDER_MODE_MARKET; - - // - mEntry = GetEntry( - symbol, - mType // - ); - - // - // XATRL ... - bool long1 = - // - (rlConditions.isVerifierSwitchedToBullish && - rlConditions.isFastBullish && - rlConditions.isSlowBearish && - rlConditions.isFastOverSlow && - atslConditions.isBullish) - // - ; - if (long1) - { - // - Add( - "XATRL", - providers // - ); - - // - pushers++; - - // - // Calculate TP and SL ... - - // - mSL = atslConditions.atsl[1]; - - // - double risk = MathAbs(mSL - mEntry); - double reward = risk * mR2R; - - // - mSL = mEntry + risk; - mTP = mEntry - reward; - - // - tp = mTP; - sl = mSL; - } - - // - result = - // - long1 - // - ; - if (result) - { - // - result = signal.Prepare( - symbol, - "XATRL", - period, - mType, - mMode, - mEntry, - volume, - mSL, - mTP // - ); - } - - // - return result; - } - - // - // Generate Supports ... - // TODO: - - // - // Tools ... - - // - // Cleanup ... - void Clean() - { - // - time = NULL; - symbol = NULL; - period = NULL; - - // - Clean(cci); - Clean(rsi); - Clean(macd); - Clean(macdSignal); - - // - rlConditions.Clean(); - mcConditions.Clean(); - tdConditions.Clean(); - hkConditions.Clean(); - cheConditions.Clean(); - ichConditions.Clean(); - strConditions.Clean(); - mrbConditions.Clean(); - vlmConditions.Clean(); - slnConditions.Clean(); - htdConditions.Clean(); - chmaConditions.Clean(); - atslConditions.Clean(); - asctConditions.Clean(); - sslcConditions.Clean(); - hullConditions.Clean(); - dmntConditions.Clean(); - adxtdConditions.Clean(); - - // - CleanSignal(); - } - - // - void GenerateScore( - double &bullishScore, - double &bearishScore // - ) - { - // - bullishScore = 0; - bearishScore = 0; - - // - double tempBullishScore = 0; - double tempBearishScore = 0; - - // - rlConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - mcConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - pvConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - slnConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - adxtdConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - strConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - cheConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - asctConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - tdConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - ichConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - hkConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - mrbConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - vlmConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - sslcConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - chmaConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - hullConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - htdConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - atslConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - dmntConditions.GenerateScore( - tempBullishScore, - tempBearishScore // - ); - bullishScore += tempBullishScore; - bearishScore += tempBearishScore; - - // - } - - // - string GenerateSummary( - bool onlyCommons = false, - bool onlyConditions = false, - bool includeScores = true, - bool ignoreFalseConditions = true, - string separator = "\n" // - ) - { - // - string result = NULL; - - // - double bullishScore = 0; - double bearishScore = 0; - GenerateScore( - bullishScore, - bearishScore // - ); - - // - string scoresStr = - // - "Scores: " + separator + - "---------------" + separator + - "Bullish: " + ToString(bullishScore) + separator + - "Bearish: " + ToString(bearishScore) + separator + - "" - // - ; - - // - string commonStr = GenerateSpecifiedCommonSummary( - this, - separator, - includeScores // - ); - - // - string pvSummary = pvConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string rlSummary = rlConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string mcSummary = mcConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string tdSummary = tdConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string hkSummary = hkConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string strSummary = strConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string cheSummary = cheConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string ichSummary = ichConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string mrbSummary = mrbConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string vlmSummary = vlmConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string slnSummary = slnConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string htdSummary = htdConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string chmaSummary = chmaConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string atslSummary = atslConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string asctSummary = asctConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string sslcSummary = sslcConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string hullSummary = hullConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string dmntSummary = dmntConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - string adxtdSummary = adxtdConditions.GenerateSummary(false, true, false, ignoreFalseConditions); - - // - string conditionsStr = - // - pvSummary + separator + - rlSummary + separator + - mcSummary + separator + - tdSummary + separator + - hkSummary + separator + - ichSummary + separator + - mrbSummary + separator + - vlmSummary + separator + - slnSummary + separator + - strSummary + separator + - cheSummary + separator + - asctSummary + separator + - sslcSummary + separator + - hullSummary + separator + - adxtdSummary + separator + - htdSummary + separator + - atslSummary + separator + - dmntSummary + separator + - chmaSummary + separator + - "" - // - ; - - // - result = - // - "[" + GetTag() + "]" + separator + - (onlyConditions - ? "" - : commonStr) + - (!includeScores - ? "" - : scoresStr) + - " " + separator + - (onlyCommons - ? "" - : conditionsStr) + - "" - // - ; - - // - return result; - } - - // - string GetTag() - { - return "XTestSetup"; - } - - // -}; - -// -// Class ... -class XSCXTestSetup : public XSCBaseAlert -{ - // - // Public ... -public: - // - // Props ... - XSCXRLHelper *rlHelper; - XSCXMCHelper *mcHelper; - XSCXPVHelper *pvHelper; - XSCXTDHelper *tdHelper; - XSCXHKHelper *hkHelper; - XSCXCHEHelper *cheHelper; - XSCXICHHelper *ichHelper; - XSCXSTRHelper *strHelper; - XSCXMRBHelper *mrbHelper; - XSCXOSCHelper *oscHelper; - XSCXVLMHelper *vlmHelper; - XSCXSLNHelper *slnHelper; - XSCXHTDHelper *hdtHelper; - XSCXASCTHelper *asctHelper; - XSCXSSLCHelper *sslcHelper; - XSCXHULLHelper *hullHelper; - XSCXATSLHelper *atslHelper; - XSCXCHMAHelper *chmaHelper; - XSCXDMNTHelper *dmntHelper; - XSCXADXTDHelper *adxtdHelper; - - // - XBarTracker barTracker; - - // - // Constructor(s) ... - void XSCXTestSetup() {} - - // - // Deconstructor ... - void ~XSCXTestSetup() - { - // - delete rlHelper; - delete mcHelper; - delete pvHelper; - delete tdHelper; - delete hkHelper; - delete cheHelper; - delete ichHelper; - delete strHelper; - delete mrbHelper; - delete oscHelper; - delete vlmHelper; - delete hdtHelper; - delete asctHelper; - delete sslcHelper; - delete hullHelper; - delete atslHelper; - delete chmaHelper; - delete dmntHelper; - delete adxtdHelper; - } - - // - // Initializer ... - bool Init( - XTestInputs &_inputs // Configurations - ) - { - // - bool result = false; - - // - result = _inputs.IsValid(); - if (!result) - { - return result; - } - - // - inputs = _inputs; - - // - // Initialize Helpers ... - - // - // XRL ... - rlHelper = new XSCXRLHelper(); - result = rlHelper.Init( - inputs.symbol, - inputs.period, - inputs.rlInputs // - ); - if (!result) - { - return result; - } - - // - // XPV ... - pvHelper = new XSCXPVHelper(); - result = pvHelper.Init( - inputs.symbol, - inputs.period, - inputs.pvInputs // - ); - if (!result) - { - return result; - } - - // - // XCHMA ... - chmaHelper = new XSCXCHMAHelper(); - result = chmaHelper.Init( - inputs.symbol, - inputs.period, - inputs.chmaInputs // - ); - if (!result) - { - return result; - } - - // - // XSLN ... - slnHelper = new XSCXSLNHelper(); - result = slnHelper.Init( - inputs.symbol, - inputs.period, - inputs.slnInputs // - ); - if (!result) - { - return result; - } - - // - // XTD ... - tdHelper = new XSCXTDHelper(); - result = tdHelper.Init( - inputs.symbol, - inputs.period, - inputs.tdInputs // - ); - if (!result) - { - return result; - } - - // - // XHTD ... - hdtHelper = new XSCXHTDHelper(); - result = hdtHelper.Init( - inputs.symbol, - inputs.period, - inputs.htdInputs // - ); - if (!result) - { - return result; - } - - // - // XATSL ... - atslHelper = new XSCXATSLHelper(); - result = atslHelper.Init( - inputs.symbol, - inputs.period, - inputs.atslInputs // - ); - if (!result) - { - return result; - } - - // - // XDMNT ... - dmntHelper = new XSCXDMNTHelper(); - result = dmntHelper.Init( - inputs.symbol, - inputs.period, - inputs.dmntInputs // - ); - if (!result) - { - return result; - } - - // - // XHK ... - hkHelper = new XSCXHKHelper(); - result = hkHelper.Init( - inputs.symbol, - inputs.period, - inputs.hkInputs // - ); - if (!result) - { - return result; - } - - // - // XCHE ... - cheHelper = new XSCXCHEHelper(); - result = cheHelper.Init( - inputs.symbol, - inputs.period, - inputs.cheInputs // - ); - if (!result) - { - return result; - } - - // - // XICH ... - ichHelper = new XSCXICHHelper(); - result = ichHelper.Init( - inputs.symbol, - inputs.period, - inputs.ichInputs // - ); - if (!result) - { - return result; - } - - // - // XSTR ... - strHelper = new XSCXSTRHelper(); - result = strHelper.Init( - inputs.symbol, - inputs.period, - inputs.strInputs // - ); - if (!result) - { - return result; - } - - // - // XMRB ... - mrbHelper = new XSCXMRBHelper(); - result = mrbHelper.Init( - inputs.symbol, - inputs.period, - inputs.mrbInputs // - ); - if (!result) - { - return result; - } - - // - // XOSC ... - oscHelper = new XSCXOSCHelper(); - result = oscHelper.Init( - inputs.symbol, - inputs.period, - inputs.oscInputs // - ); - if (!result) - { - return result; - } - - // - // XVLM ... - vlmHelper = new XSCXVLMHelper(); - result = vlmHelper.Init( - inputs.symbol, - inputs.period, - inputs.vlmInputs // - ); - if (!result) - { - return result; - } - - // - // XMC ... - mcHelper = new XSCXMCHelper(); - result = mcHelper.Init( - inputs.symbol, - inputs.period, - inputs.mcInputs // - ); - if (!result) - { - return result; - } - - // - // XASCT ... - asctHelper = new XSCXASCTHelper(); - result = asctHelper.Init( - inputs.symbol, - inputs.period, - inputs.asctInputs // - ); - if (!result) - { - return result; - } - - // - // XSSLC ... - sslcHelper = new XSCXSSLCHelper(); - result = sslcHelper.Init( - inputs.symbol, - inputs.period, - inputs.sslcInputs // - ); - if (!result) - { - return result; - } - - // - // XHULL ... - hullHelper = new XSCXHULLHelper(); - result = hullHelper.Init( - inputs.symbol, - inputs.period, - inputs.hullInputs // - ); - if (!result) - { - return result; - } - - // - // XADXTD ... - adxtdHelper = new XSCXADXTDHelper(); - result = adxtdHelper.Init( - inputs.symbol, - inputs.period, - inputs.adxtdInputs // - ); - if (!result) - { - return result; - } - - // - // Initial Bar Tracker ... - result = barTracker.Init( - inputs.symbol, - inputs.period // - ); - if (!result) - { - return result; - } - - // - return result; - } - - // - // Getter(s) / Setter(s) ... - - // - string GetSymbol() - { - return inputs.symbol; - } - - // - ENUM_TIMEFRAMES GetPeriod() - { - return inputs.period; - } - - // - XTestInputs GetInputs() - { - return inputs; - } - - // - bool SetInputs( - XTestInputs &_inputs // Configurations - ) - { - return Init(_inputs); - } - - // - // Tools ... - - // - // Retrieve Conditions ... - bool GetConditions( - XTestConditions &conditions, // - int barIndex = 0, // - int loopback = 5 // - ) - { - // - bool result = false; - - // - conditions.Clean(); - - // - conditions.symbol = GetSymbol(); - conditions.period = GetPeriod(); - conditions.time = TimeCurrent(); - - // - // Checking Can Process Bar ... - result = barTracker.CanProcessBar(); - if (!result) - { - return result; - } - - // - result = rlHelper.GetConditions( - conditions.rlConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = hdtHelper.GetConditions( - conditions.htdConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = slnHelper.GetConditions( - conditions.slnConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = chmaHelper.GetConditions( - conditions.chmaConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = atslHelper.GetConditions( - conditions.atslConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = dmntHelper.GetConditions( - conditions.dmntConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = pvHelper.GetConditions( - conditions.pvConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = tdHelper.GetConditions( - conditions.tdConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = hkHelper.GetConditions( - conditions.hkConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = cheHelper.GetConditions( - conditions.cheConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = ichHelper.GetConditions( - conditions.ichConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = strHelper.GetConditions( - conditions.strConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = mrbHelper.GetConditions( - conditions.mrbConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = mcHelper.GetConditions( - conditions.mcConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = asctHelper.GetConditions( - conditions.asctConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = vlmHelper.GetConditions( - conditions.vlmConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = sslcHelper.GetConditions( - conditions.sslcConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = hullHelper.GetConditions( - conditions.hullConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - result = adxtdHelper.GetConditions( - conditions.adxtdConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - - // - oscHelper.CopyCCI( - barIndex, - loopback, - conditions.cci // - ); - oscHelper.CopyRSI( - barIndex, - loopback, - conditions.rsi // - ); - oscHelper.CopyMACD( - barIndex, - loopback, - conditions.macd // - ); - oscHelper.CopyMACDSignal( - barIndex, - loopback, - conditions.macdSignal // - ); - - // - // Generating Signal ... - double mTP = 0; - double mSL = 0; - bool hasSignal = conditions.GenerateSignal( - mTP, - mSL, - inputs.volume, - inputs.tpPoint, - inputs.slPoint // - ); - if (hasSignal) - { - barTracker.Waits(); - } - - // - return result; - } - - // - // Protected ... -protected: - // - // Private ... -private: - // - // Props ... - XTestInputs inputs; // Setup Configurations ... -}; - -// \ No newline at end of file diff --git a/Test/x-saherelm.test.xea.mq5 b/Test/x-saherelm.test.xea.mq5 deleted file mode 100644 index 95efcd5f..00000000 --- a/Test/x-saherelm.test.xea.mq5 +++ /dev/null @@ -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; - } - - // -}; - -// \ No newline at end of file diff --git a/compile.js b/compile.js index 6db4a8a6..e45be901 100644 --- a/compile.js +++ b/compile.js @@ -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 { diff --git a/pack.js b/pack.js index 403f50d5..a54d45a9 100644 --- a/pack.js +++ b/pack.js @@ -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 ]; // diff --git a/package.json b/package.json index 3671e816..3d46faf6 100644 --- a/package.json +++ b/package.json @@ -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" },