From 46967136d34be91ed1f9544a433915611d09f312 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 27 Jun 2024 20:22:41 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x121.setup.xea.mq5 | 434 +- Classes/x-saherelm.xea.class.mq5 | 2 + .../BKP/Old/x-saherelm.x121.setup.xea.mq5 | 5878 +++++++++++++++++ Experts/x-saherelm.x121.ea.mq5 | 8 +- Libraries/x-saherelm.xtrade.lib.mq5 | 92 + 5 files changed, 6099 insertions(+), 315 deletions(-) create mode 100644 Documents/BKP/Old/x-saherelm.x121.setup.xea.mq5 diff --git a/Classes/x-saherelm.x121.setup.xea.mq5 b/Classes/x-saherelm.x121.setup.xea.mq5 index 342aa28e..0bf9cdf5 100644 --- a/Classes/x-saherelm.x121.setup.xea.mq5 +++ b/Classes/x-saherelm.x121.setup.xea.mq5 @@ -204,6 +204,53 @@ struct XTradeInfo return result; } + // + bool IsOwn(XSignal &signal) + { + // + return IsOwn( + signal.symbol, + signal.provider, + signal.time, + signal.period, + signal.type // + ); + } + + // + bool IsOwn( + string _symbol, + string _provider, + datetime _time, + ENUM_TIMEFRAMES _period, + ENUM_POSITION_TYPE _type // + ) + { + // + bool result = false; + + // + ENUM_X_POSITION_TYPES iType = ToPositionType(_type); + + // + result = + // + IsValid(_symbol) && + IsValid(_provider) && + IsValid(_period) && + // + symbol == _symbol && + provider == _provider && + period == _period && + type == iType && + time == _time + // + ; + + // + return result; + } + // // Data Collector ... @@ -547,6 +594,7 @@ struct XTradeInfo // result = IsValid() && + allowGrid && distance > 0 && volumeMultiplier > 0; if (!result) @@ -765,6 +813,7 @@ struct XTradeInfo entry > 0 && volume > 0 && distance > 0 && + allowRecover && volumeMultiplier > 0 // ; @@ -2026,6 +2075,77 @@ public: Finish(infoIDX); } + // + bool AllowToGrid( + XSignal &signal // + ) + { + // + bool result = false; + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + int infoIDX = FindIndex(signal); + result = IsValidIndex(infoIDX); + if (!result) + { + return result; + } + + // + data[infoIDX].allowGrid = true; + data[infoIDX].PrepareNextGrid( + GridDistance(), + GridVolumeMultiplier() // + ); + + // + return result; + } + + // + bool AllowToRecovery( + XSignal &signal // + ) + { + // + bool result = false; + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + int infoIDX = FindIndex(signal); + result = IsValidIndex(infoIDX); + if (!result) + { + return result; + } + + // + data[infoIDX].allowRecover = true; + data[infoIDX].PrepareNextRecovery( + GridDistance(), + GridVolumeMultiplier(), + signal.type // + ); + + // + return result; + } + // // Sync ... void Sync() @@ -4600,10 +4720,6 @@ public: eSignals // ); } - else - { - Alert("INNNValid Signal"); - } } // @@ -4640,7 +4756,7 @@ public: // Youngest Age of Positions longest as enough // Make State of Signalling to Force State for Recieving // Signal and Clear their Tp and SL for allowing hedges ... - EQMHandleForceState(signals); + // EQMHandleForceState(signals); // if (mForce) // { // result = true; @@ -4831,23 +4947,6 @@ protected: // Alert(message); - // - EQMHandleForceState(signals); - - // - return; - } - - // - bool isNumberOfPositionsPassed = IsNumberOfPositionsPassed(); - if (!isNumberOfPositionsPassed) - { - // - string message = "Max Allowed Signals Reached ..."; - - // - Alert(message); - // return; } @@ -4954,39 +5053,6 @@ protected: return result; } - // - bool IsNumberOfPositionsPassed() - { - // - bool result = false; - - // - // int maxAllowed = MaxPositionsForce(); - // result = maxAllowed <= 0; - // if (result) - // { - // return result; - // } - - // // - // XPosition positions[]; - // int positionsCount = mTrader.GetPositions(positions); - // result = !IsValidSize(positionsCount); - // if (result) - // { - // return result; - // } - - // // - // result = positionsCount < maxAllowed; - - // - result = true; - - // - return result; - } - // // Private ... private: @@ -5296,258 +5362,6 @@ private: void EQMHandleForceState(XSignal &forceSignals[]) { // - // Validate Force Marigin ... - double marigin = mTrader.mAccount.GetMargin(); - double minFreeMarigin = MinFreeMargingForOpenTrades(); - double forceMargin = minFreeMarigin * 2; // TODO: Make It Configurable - bool isMarginForce = marigin >= forceMargin; - bool isMarginHotForce = marigin >= forceMargin * 3; - - // - // Retrieving Positions ... - XPosition positions[]; - int positionsCount = mTrader.GetPositions(positions); - if (!IsValidSize(positionsCount)) - { - // - mForce = false; - return; - } - bool isPositionsCountHotForce = positionsCount >= 10; - - // - XPosition oldest; - int oldestAge = GetOldest( - oldest, - positions // - ); - - // - // Check Force State ... - bool isForce = isMarginForce; // && oldestAge >= 288; - if (!isForce) - { - // - if (mForce) - { - mForce = false; - } - return; - } - else - { - mForce = true; - } - - // - // Prevent Moving Forward From Non Force State ... - if (!mForce) - { - return; - } - - // - double minProfitPerTrade = MinProfitPerTrade(); - double minProfitPerVolumeFactor = MinProfitPerVolumeFactor(); - - // - double profit = SpecifiedCalculatePositionsProfit(positions); - double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( - positions, - minProfitPerTrade, - minProfitPerVolumeFactor // - ); - - // - XSymbolPositions symbolPositions[]; - int symbolPositionsCount = ExtractSymbolPositions( - positions, - symbolPositions, - minProfitPerTrade, - minProfitPerVolumeFactor // - ); - if (!IsValidSize(symbolPositionsCount)) - { - return; - } - - // - XSignal signals[]; - int forceSignalsCount = ArraySize(forceSignals); - if (IsValidSize(forceSignalsCount)) - { - // - // Check if Symbol Contains or Not ... - for (int i = 0; i < forceSignalsCount; i++) - { - // - XSignal iForceSignal = forceSignals[i]; - - // - int symbolIDX = -1; - bool isSymbolContains = IsContainsSymbol( - iForceSignal.symbol, - symbolIDX, - symbolPositions // - ); - if (!isSymbolContains) - { - // - AddRef( - iForceSignal, - signals // - ); - - // - continue; - } - else - { - // - ENUM_POSITION_TYPE iType = iForceSignal.type; - bool isLong = IsLong(iType); - - // - XSymbolPositions iSymbolPositions = symbolPositions[symbolIDX]; - if (isLong) - { - // - if (iSymbolPositions.longsProfit > 0) - { - // - if (!isMarginHotForce && !isPositionsCountHotForce) - { - // - AddRef( - iForceSignal, - signals // - ); - } - else - { - } - } - else - { - // - // In Drawdown ... - if (isMarginHotForce && !isPositionsCountHotForce) - { - } - else - { - } - } - } - else - { - // - if (iSymbolPositions.shortsProfit > 0) - { - // - if (!isMarginHotForce && !isPositionsCountHotForce) - { - // - AddRef( - iForceSignal, - signals // - ); - } - else - { - } - } - else - { - // - // In Drawdown ... - if (!isMarginHotForce && !isPositionsCountHotForce) - { - } - else - { - } - } - } - } - } - } - - // - int signalsCount = ArraySize(signals); - if (IsValidSize(signalsCount)) - { - EQMExecuteSignals(signals); - } - else - { - // - // Handle CLosing ... - if (!isMarginHotForce) - { - return; - } - - // - for (int i = 0; i < symbolPositionsCount; i++) - { - // - XSymbolPositions iSymbolPositions = symbolPositions[i]; - - // - if (!iSymbolPositions.HasChild()) - { - continue; - } - - // - if (iSymbolPositions.profit > 0) - { - continue; - } - - // - XPosition iOldest; - int oldestAge = GetOldest( - iOldest, - iSymbolPositions.positions // - ); - if (oldestAge <= 140) - { - continue; - } - - // - int maxInDPIDX = FindMaxDrawdownIndex( - iSymbolPositions.positions // - ); - if (!IsValidIndex(maxInDPIDX)) - { - continue; - } - - // - XPosition maxInDP = iSymbolPositions.positions[maxInDPIDX]; - - // - string comment = XEQMSupportToken + " Close due Max In D ..."; - bool isClosed = mTrader.Close( - maxInDP.ticket, - comment // - ); - if (isClosed) - { - // - string message = XEQMSupportToken + " Close (" + ToString(maxInDP.ticket) + ") due Max In D ..."; - - // - Alert(message); - } - } - } - - // - // Log("symbolPositionsCount: " + ToString(symbolPositionsCount)); } // @@ -5569,7 +5383,7 @@ private: XSignal signals[]; // - if (isValid || pushers > 1) + if (isValid) { // bool canSupport = @@ -5619,9 +5433,7 @@ private: // if (ArraySize(signals) > 0) { - // - // EQMExecuteSignals(signals); - EQMHandleForceState(signals); + EQMExecuteSignals(signals); } } diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index 7651f72c..919d3673 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -177,6 +177,8 @@ public: // double GetDrawdownPercent() { + // + CalculateMaxDrawdown(); return mDrawdownPercent; } diff --git a/Documents/BKP/Old/x-saherelm.x121.setup.xea.mq5 b/Documents/BKP/Old/x-saherelm.x121.setup.xea.mq5 new file mode 100644 index 00000000..3b6ab890 --- /dev/null +++ b/Documents/BKP/Old/x-saherelm.x121.setup.xea.mq5 @@ -0,0 +1,5878 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCX121SetupCycle +// Description: provides implementation of X121 +// Setup on Specified Market Cycle ... +// +// +// 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.xea.class.mq5" +#include "../Classes/x-saherelm.x121.setup.cycle.class.mq5" + +// +// Definitions ... + +// +// Model all Trades Data as this Structure ... +struct XTradeInfo +{ + // + int pushers; // Signal Pushers + datetime time; // Issue Time (Open Position) + string symbol; // Trading Symbol + double entry; // Entry Price + double volume; // Volume + string provider; // Signaller + ENUM_TIMEFRAMES period; // Trading Timeframe + ENUM_X_POSITION_TYPES type; // Position Type + + // + ulong ticket; // Position Ticket + double profit; // Profit on Close + double commission; // Commission + double swap; // Swap + string message; // Close Reason + datetime endTime; // End Time + + // + X121SetupConditions cConditions; // Generated Current Conditions + X121SetupConditions sConditions; // Generated Short Conditions + X121SetupConditions mConditions; // Generated Medium Conditions + X121SetupConditions lConditions; // Generated Long Conditions + X121SetupConditions hConditions; // Generated Hind Conditions + + // + // Constructor ... + void XTradeInfo() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + time = NULL; + type = NULL; + symbol = NULL; + period = NULL; + endTime = NULL; + message = NULL; + provider = NULL; + + // + swap = 0; + entry = 0; + ticket = 0; + profit = 0; + volume = 0; + pushers = 0; + commission = 0; + + // + cConditions.Clean(); + sConditions.Clean(); + mConditions.Clean(); + lConditions.Clean(); + hConditions.Clean(); + + // + ResetGrid(); + ResetSupport(); + ResetRecovery(); + } + + // + bool Fill( + const XSignal &_signal, + int _pushers, + bool _allowGrid, + bool _allowRecover, + bool _allowSupport, + X121SetupConditions &_cConditions, + X121SetupConditions &_sConditions, + X121SetupConditions &_mConditions, + X121SetupConditions &_lConditions, + X121SetupConditions &_hConditions // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_signal.symbol) && + IsValid(_signal.period) && + IsValid(_signal.provider) + // + ; + + // + if (!result) + { + return result; + } + + // + pushers = _pushers; + time = _signal.time; + entry = _signal.entry; + symbol = _signal.symbol; + period = _signal.period; + volume = _signal.volume; + provider = _signal.provider; + type = ToPositionType(_signal.type); + + // + cConditions = _cConditions; + sConditions = _sConditions; + mConditions = _mConditions; + lConditions = _lConditions; + hConditions = _hConditions; + + // + allowGrid = _allowGrid; + allowRecover = _allowRecover; + allowSupport = _allowSupport; + + // + return result; + } + + // + bool IsOwn( + ulong _ticket // + ) + { + // + bool result = false; + + // + result = _ticket == ticket; + + // + return result; + } + + // + bool IsOwn( + string _symbol, + string _provider, + ENUM_TIMEFRAMES _period // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_symbol) && + IsValid(_provider) && + IsValid(_period) && + // + symbol == _symbol && + provider == _provider && + period == _period + // + ; + + // + return result; + } + + // + bool IsOwn(XSignal &signal) + { + // + return IsOwn( + signal.symbol, + signal.provider, + signal.time, + signal.period, + signal.type // + ); + } + + // + bool IsOwn( + string _symbol, + string _provider, + datetime _time, + ENUM_TIMEFRAMES _period, + ENUM_POSITION_TYPE _type // + ) + { + // + bool result = false; + + // + ENUM_X_POSITION_TYPES iType = ToPositionType(_type); + + // + result = + // + IsValid(_symbol) && + IsValid(_provider) && + IsValid(_period) && + // + symbol == _symbol && + provider == _provider && + period == _period && + type == iType && + time == _time + // + ; + + // + return result; + } + + // + // Data Collector ... + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) + // + ; + + // + return result; + } + + // + int GetAge() + { + // + int result = -1; + + // + if (!IsValid(symbol) || + !IsValid(time) || + !IsValid(endTime) || + !IsValid(period)) + { + return result; + } + + // + int startIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + int endIndex = iBarShift( + symbol, + period, + endTime, + false // + ); + + // + result = MathAbs(startIndex - endIndex); + + // + return result; + } + + // + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + (profit >= 0 + ? "Profit" + : "Loss") + + "\\" + + provider + "_" + + ToString(ticket) + "_" + + ToString(period) + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + string GetSignalFileName() + { + // + string result = NULL; + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + provider + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + string ToString( + bool onlySignals = false // + ) + { + // + string result = NULL; + + // + string cConditionsStr = cConditions + .GenerateSummary( + false, // Only Commons ... + true, // Only Conditions ... + false, // Include Score ... + false // Include False Conditions ... + ); + string sConditionsStr = sConditions + .GenerateSummary( + false, // Only Commons ... + true, // Only Conditions ... + false, // Include Score ... + false // Include False Conditions ... + ); + string mConditionsStr = mConditions + .GenerateSummary( + false, // Only Commons ... + true, // Only Conditions ... + false, // Include Score ... + false // Include False Conditions ... + ); + string lConditionsStr = lConditions + .GenerateSummary( + false, // Only Commons ... + true, // Only Conditions ... + false, // Include Score ... + false // Include False Conditions ... + ); + string hConditionsStr = hConditions + .GenerateSummary( + false, // Only Commons ... + true, // Only Conditions ... + false, // Include Score ... + false // Include False Conditions ... + ); + + // + int age = GetAge(); + + // + result = + // + (onlySignals + ? "" + : ToString("Ticket", ticket)) + + ToString("Symbol", symbol) + + ToString("Period", period) + + ToString("Entry", entry) + + ToString("Provider", provider) + + ToString("Type", ToString(type)) + + ToString("Time", time) + + ToString("Pushers", pushers) + + (onlySignals + ? "" + : "-------------" + "\n" + + ToString("Volume", volume) + + ToString("Profit", profit) + + ToString("Commission", commission) + + ToString("Swap", swap) + + ToString("End Time", endTime) + + ToString("Age", age) + + ToString("Message", message)) + + "-------------" + "\n" + + "Conditions" + "\n" + + "-------------" + "\n" + + "-------------" + "\n" + + "CURRENT [" + ToString(cConditions.period) + "]" + "\n" + + "-------------" + "\n" + + cConditionsStr + "\n" + + "-------------" + "\n" + + "SHORT [" + ToString(sConditions.period) + "]" + "\n" + + "-------------" + "\n" + + sConditionsStr + "\n" + + "-------------" + "\n" + + "MEDIUM [" + ToString(mConditions.period) + "]" + "\n" + + "-------------" + "\n" + + mConditionsStr + "\n" + + "-------------" + "\n" + + "LONG [" + ToString(lConditions.period) + "]" + "\n" + + "-------------" + "\n" + + lConditionsStr + "\n" + + "-------------" + "\n" + + "HIND [" + ToString(hConditions.period) + "]" + "\n" + + "-------------" + "\n" + + hConditionsStr + "\n" + + // + "" + // + ; + + // + return result; + } + + // + // These are Some Helpers for Trading Controls and do not relate to Main + // purpose of Trade Handler ... + + // + // Supporting ... + + // + bool allowSupport; // Allow Support + + // + void ResetSupport() + { + allowSupport = false; + } + + // + // Retrieve Support Signal ... + bool HasSupport( + XSignal &support // + ) + { + // + bool result = false; + + // + return result; + } + + // + // Grid System Calculations ... + + // + int gLevel; // Number of Grids + bool allowGrid; // Allow Grid + double gEntry; // Represents Next Grid Signal's Entry + double gVolume; // Represent Next Grid Signal's Volume + + // + void ResetGrid() + { + // + gEntry = 0; + gLevel = 0; + gVolume = 0; + + // + allowGrid = false; + } + + // + void SetGrid( + double nextEntry, + double nextVolume // + ) + { + // + gEntry = nextEntry; + gVolume = nextVolume; + } + + // + // Prepare Data For Next Grid ... + void PrepareNextGrid( + double distance, + double volumeMultiplier // + ) + { + // + bool isValid = + // + IsValid() && + entry > 0 && + volume > 0 && + distance > 0 && + volumeMultiplier > 0 + // + ; + bool isLong = IsLong(type); + + // + double distancePrice = PointToPrice( + distance, + symbol // + ); + + // + double selectedEntry = + gEntry <= 0 + ? entry + : gEntry; + double selectedVolume = + gVolume <= 0 + ? volume + : gVolume; + + // + double nextEntry = + isLong + ? selectedEntry - distancePrice + : selectedEntry + distancePrice; + double nextVolume = selectedVolume * volumeMultiplier; + + // + SetGrid( + nextEntry, + nextVolume // + ); + } + + // + // Check if a Grid Signal Exists Prepared and + // Provide it ... + bool HasGrid( + XSignal &signal, // Result Signal + double distance, + double volumeMultiplier // + ) + { + // + bool result = false; + + // + signal.Clean(); + + // + result = IsValid() && + allowGrid && + distance > 0 && + volumeMultiplier > 0; + if (!result) + { + return result; + } + + // + bool isLong = IsLong(type); + + // + ENUM_POSITION_TYPE gType = + isLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + double cEntry = GetEntry( + symbol, + gType // + ); + + // + result = + isLong + ? cEntry <= gEntry + : cEntry >= gEntry; + if (!result) + { + return result; + } + + // + result = signal.Prepare( + symbol, + provider, + period, + gType, + X_ORDER_MODE_MARKET, + cEntry, + gVolume, + 0, // SL ... + 0 // TP ... + ); + + // + if (result) + { + // + // set Support Token ... + string comment = GenerateSupportTag(ticket); + signal.comment = comment; + + // + PrepareNextGrid( + distance, + volumeMultiplier // + ); + + // + gLevel++; + } + + // + return result; + } + + // + // Recovery Zone System ... + + // + bool allowRecover; // Allow Recover + ENUM_POSITION_TYPE rLastRecoveryType; // Last Executed Recovery Signal's Type + double rLongEntry; // Represent Next Recovery Long Signal's Entry + double rShortEntry; // Represent Next Recovery Short Signal's Entry + double rVolume; // Represent Next Recovery Signal's Volume + double rZoneUpper; // Zone Recovery Upper Bound + double rZoneLower; // Zone Recovery Lower Bound + int rLevel; // Number of Recoveries + + // + void ResetRecovery() + { + // + rLevel = 0; + rVolume = 0; + rLongEntry = 0; + rZoneUpper = 0; + rZoneLower = 0; + rShortEntry = 0; + + // + allowRecover = false; + } + + // + void SetRecovery( + double nextLongEntry, + double nextShortEntry, + double zoneUpper, + double zoneLower, + double nextVolume // + ) + { + // + rVolume = nextVolume; + rZoneUpper = zoneUpper; + rZoneLower = zoneLower; + rLongEntry = nextLongEntry; + rShortEntry = nextShortEntry; + } + + // + void PrepareNextRecovery( + double distance, // Define Target Based On Zones + double volumeMultiplier, // Volume Multiplier + ENUM_POSITION_TYPE lastType // Last Type + ) + { + // + bool isValid = + // + IsValid() && + entry > 0 && + volume > 0 && + distance > 0 && + volumeMultiplier > 0 + // + ; + + // + bool isLong = IsLong(lastType); + + // + double distancePrice = PointToPrice( + distance, + symbol // + ); + + // + double selectedEntry = + isLong + ? rLongEntry <= 0 + ? entry + : rLongEntry + : rShortEntry <= 0 + ? entry + : rShortEntry; + double selectedVolume = + rVolume <= 0 + ? volume + : rVolume; + + // + double nextLongEntry = + isLong + ? selectedEntry + : selectedEntry + distancePrice; + double nextShortEntry = + isLong + ? selectedEntry - distancePrice + : selectedEntry; + + // + double nextVolume = selectedVolume * volumeMultiplier; + // rLevel % 2 == 1 + // ? volume + // : volume * volumeMultiplier; + + // + double zoneUpper = + rZoneUpper > 0 + ? rZoneUpper + : isLong + ? entry + distancePrice + : entry + (distancePrice * 2); + double zoneLower = + rZoneLower > 0 + ? rZoneLower + : isLong + ? entry + (distancePrice * 2) + : entry - distancePrice; + + // + SetRecovery( + nextLongEntry, + nextShortEntry, + zoneUpper, + zoneLower, + nextVolume // + ); + + // + rLastRecoveryType = lastType; + } + + // + // Check if a Recovery Signal Exists Prepared and + // Provide it ... + bool HasRecovery( + XSignal &signal, // Result Signal ... + double distance, + double volumeMultiplier // + ) + { + // + bool result = false; + + // + signal.Clean(); + + // + result = + // + IsValid() && + entry > 0 && + volume > 0 && + distance > 0 && + allowRecover && + volumeMultiplier > 0 + // + ; + if (!result) + { + return result; + } + + // + double distancePrice = PointToPrice( + distance, + symbol // + ); + + // + bool isLong = IsLong(type); + bool isLastLong = IsLong(rLastRecoveryType); + + // + // Check For Long Recovery ... + double cLongEntry = GetEntry( + symbol, + POSITION_TYPE_BUY // + ); + bool hasLongRecovery = + !isLastLong && + rLongEntry > 0 && cLongEntry >= rLongEntry; + + // + // Check For Short Recovery ... + double cShortEntry = GetEntry( + symbol, + POSITION_TYPE_SELL // + ); + bool hasShortRecovery = + isLastLong && + rShortEntry > 0 && + cShortEntry <= rShortEntry; + + // + result = hasLongRecovery || hasShortRecovery; + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE rType = + hasLongRecovery + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + double rEntry = + hasLongRecovery + ? cLongEntry + : cShortEntry; + + // + double rTP = + hasLongRecovery + ? rZoneUpper + : rZoneLower; + + // + double rSL = + hasLongRecovery + ? rZoneLower + : rZoneUpper; + + // + result = signal.Prepare( + symbol, + provider, + period, + rType, + X_ORDER_MODE_MARKET, + rEntry, + rVolume, + 0, // rSL, // SL ... + 0 // rTP // TP ... + ); + if (result) + { + // + // set Support Token ... + string comment = GenerateSupportTag(ticket); + signal.comment = comment; + + // + rLevel++; + + // + PrepareNextRecovery( + distance, + volumeMultiplier, + rType // + ); + } + + // + return result; + } +}; + +// +// a Class For Read and Write Trade Info Data in Files ... +class XTradeInfoCollector +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + void XTradeInfoCollector( + string _path = NULL // Base Path + ) + { + // + mAccount = new XSCAccount(); + + // + if (IsValid(_path)) + { + mPath = _path; + } + else + { + mPath = "XTradeInfo" + "\\" + mAccount.GetCompany(); + } + } + + // + // Deconstructor ... + void ~XTradeInfoCollector() {} + + // + bool IsExists(XTradeInfo &item) + { + // + bool result = false; + + // + int mHandler = GetFileHandlerForRead(item); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + // + bool Save(XTradeInfo &item) + { + // + bool result = false; + + // + // Check info is Valid ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + string content = item.ToString(); + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + bool SaveSignal(XTradeInfo &item) + { + // + bool result = false; + + // + string content = item.ToString(); + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetSignalFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + + // + string mPath; // Base Path ... + + // + XSCAccount *mAccount; + + // + string GetFilePath(XTradeInfo &item) + { + // + string fileName = item.GetFileName(); + + // + return GetFilePath(fileName); + } + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + string GetSignalFilePath(XTradeInfo &item) + { + // + string fileName = item.GetSignalFileName(); + + // + return GetSignalFilePath(fileName); + } + string GetSignalFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Signals" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForRead(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetFileHandlerForWrite(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetSignalFileHandlerForRead(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetSignalFileHandlerForWrite(XTradeInfo &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } +}; + +// +// a Class for Holding all required data for Specified Trade +// such as: +// - Signal; +// - Position; +// - Conditions; +// - Scores; +// - etc ... +class XTradeHandler +{ + // +public: + // + // Props ... + + // + // Constructor ... + void XTradeHandler( + XSCTrade *trade // an Instance of Trader Class + ) + { + // + Clean(data); + SetSave(false); + mTrader = trade; + collector = new XTradeInfoCollector(); + } + + // + // Getter(s) / Setter(s) ... + + // + // Others ... + + // + bool GetSave() + { + return mSave; + } + + // + void SetSave(bool value) + { + mSave = value; + } + + // + bool GetSaveSignalsOnly() + { + return mSaveSignalsOnly; + } + + // + void SetSaveSignalsOnly(bool value) + { + mSaveSignalsOnly = value; + } + + // + // Hedging ... + + // + double MinProfitPerTrade() + { + return mMinProfitPerTrade; + } + + // + void MinProfitPerTrade(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinProfitPerTrade = value; + } + + // + double MinProfitPerVolumeFactor() + { + return mMinProfitPerVolumeFactor; + } + + // + void MinProfitPerVolumeFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + mMinProfitPerVolumeFactor = value; + } + + // + // Trailling Stop ... + + // + bool AllowTrailStop() + { + return mAllowTrailStop; + } + + // + void AllowTrailStop(bool value) + { + mAllowTrailStop = value; + } + + // + bool DisableTrailingWhenOpposit() + { + return mDisableTrailingWhenOpposit; + } + + // + void DisableTrailingWhenOpposit(bool value) + { + mDisableTrailingWhenOpposit = value; + } + + // + double NextTrailPoint() + { + return mNextTrailPoint; + } + + // + void NextTrailPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mNextTrailPoint = value; + } + + // + double FirstTrailPoint() + { + return mFirstTrailPoint; + } + + // + void FirstTrailPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mFirstTrailPoint = value; + } + + // + double NextTrailDistance() + { + return mNextTrailDistance; + } + + // + void NextTrailDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mNextTrailDistance = value; + } + + // + double FirstTrailDistance() + { + return mFirstTrailDistance; + } + + // + void FirstTrailDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mFirstTrailDistance = value; + } + + // + bool EnableTrailling() + { + // + bool result = false; + + // + result = + // + AllowTrailStop() && + NextTrailPoint() > 0 && + FirstTrailPoint() > 0 && + NextTrailDistance() > 0 && + FirstTrailDistance() > 0 + // + ; + + // + return result; + } + + // + // Supporting ... + + // + bool AllowSupport() + { + return mAllowSupport; + } + + // + void AllowSupport(bool value) + { + mAllowSupport = value; + } + + // + bool SupportOnlyForces() + { + return mSupportOnlyForces; + } + + // + void SupportOnlyForces(bool value) + { + mSupportOnlyForces = value; + } + + // + double SupportDistance() + { + return mSupportDistance; + } + + // + void SupportDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSupportDistance = value; + } + + // + int MaxNumberOfSupports() + { + return mMaxNumberOfSupports; + } + + // + void MaxNumberOfSupports(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxNumberOfSupports = value; + } + + // + double SupportVolumeMultiplier() + { + return mSupportVolumeMultiplier; + } + + // + void SupportVolumeMultiplier(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupportVolumeMultiplier = value; + } + + // + double MaxAllowedSupportVolume() + { + return mMaxAllowedSupportVolume; + } + + // + void MaxAllowedSupportVolume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mMaxAllowedSupportVolume = value; + } + + // + bool EnableSupport() + { + // + bool result = false; + + // + result = + // + AllowSupport() && + SupportDistance() > 0 && + MaxNumberOfSupports() >= 0 && + SupportVolumeMultiplier() > 0 + // + ; + + // + return result; + } + + // + // Grid ... + + // + bool AllowGrid() + { + return mAllowGrid; + } + + // + void AllowGrid(bool value) + { + mAllowGrid = value; + } + + // + bool GridOnlyForces() + { + return mGridOnlyForces; + } + + // + void GridOnlyForces(bool value) + { + mGridOnlyForces = value; + } + + // + int MaxNumberOfGrids() + { + return mMaxNumberOfGrids; + } + + // + void MaxNumberOfGrids(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxNumberOfGrids = value; + } + + // + double GridDistance() + { + return mGridDistance; + } + + // + void GridDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mGridDistance = value; + } + + // + double GridVolumeMultiplier() + { + return mGridVolumeMultiplier; + } + + // + void GridVolumeMultiplier(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mGridVolumeMultiplier = value; + } + + // + double MaxAllowedGridVolume() + { + return mMaxAllowedGridVolume; + } + + // + void MaxAllowedGridVolume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mMaxAllowedGridVolume = value; + } + + // + // Check Grid Properties to Validate it's Enable or not ... + bool EnableGrid() + { + // + bool result = false; + + // + result = + // + AllowGrid() && + GridDistance() > 0 && + MaxNumberOfGrids() >= 0 && + GridVolumeMultiplier() > 0 + // + ; + + // + return result; + } + + // + // Recovery System ... + + // + bool AllowRecovery() + { + return mAllowRecovery; + } + + // + void AllowRecovery(bool value) + { + mAllowRecovery = value; + } + + // + bool RecoverOnlyForces() + { + return mRecoverOnlyForces; + } + + // + void RecoverOnlyForces(bool value) + { + mRecoverOnlyForces = value; + } + + // + int MaxNumberOfRecoveries() + { + return mMaxNumberOfRecoveries; + } + + // + void MaxNumberOfRecoveries(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxNumberOfRecoveries = value; + } + + // + double RecoveryDistance() + { + return mRecoveryDistance; + } + + // + void RecoveryDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRecoveryDistance = value; + } + + // + double RecoveryVolumeMultiplier() + { + return mRecoveryVolumeMultiplier; + } + + // + void RecoveryVolumeMultiplier(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRecoveryVolumeMultiplier = value; + } + + // + double MaxAllowedRecoveryVolume() + { + return mMaxAllowedRecoveryVolume; + } + + // + void MaxAllowedRecoveryVolume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mMaxAllowedRecoveryVolume = value; + } + + // + // Check Recovery Properties to Validate it's Enable or not ... + bool EnableRecovery() + { + // + bool result = false; + + // + result = + // + AllowRecovery() && + RecoveryDistance() > 0 && + MaxNumberOfRecoveries() >= 0 && + RecoveryVolumeMultiplier() > 0 + // + ; + + // + return result; + } + + // + // Tools ... + + // + int Count() + { + return ArraySize(data); + } + + // + int FindIndex(ulong ticket) + { + // + int result = -1; + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XTradeInfo iInfo = data[i]; + + // + bool isOwn = iInfo.IsOwn( + ticket // + ); + if (isOwn) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + int FindIndex(XSignal &signal) + { + // + int result = -1; + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XTradeInfo iInfo = data[i]; + + // + bool isOWN = + // + iInfo.time == signal.time && + iInfo.symbol == signal.symbol && + iInfo.volume == signal.volume && + iInfo.period == signal.period && + iInfo.provider == signal.provider && + iInfo.type == ToPositionType(signal.type) + // + ; + + // + if (isOWN) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + void Add( + XSignal &signal, + int pushers, + bool allowGrid, + bool allowRecover, + bool allowSupport, + X121SetupConditions &cConditions, + X121SetupConditions &sConditions, + X121SetupConditions &mConditions, + X121SetupConditions &lConditions, + X121SetupConditions &hConditions // + ) + { + // + XTradeInfo info; + bool isFilled = info.Fill( + signal, + pushers, + allowGrid, + allowRecover, + allowSupport, + cConditions, + sConditions, + mConditions, + lConditions, + hConditions // + ); + if (!isFilled) + { + return; + } + + // + AddRef( + info, + data // + ); + + // + if (GetSaveSignalsOnly()) + { + collector.SaveSignal(info); + } + } + + // + void Remove(XSignal &signal) + { + // + int infoIDX = FindIndex(signal); + if (!IsValidIndex(infoIDX)) + { + return; + } + + // + ArrayRemove( + data, + infoIDX, + 1 // + ); + } + + // + void Update(XSignal &signal) + { + // + if (!signal.IsValid() || !signal.IsExecuted()) + { + return; + } + + // + int infoIDX = FindIndex(signal); + if (!IsValidIndex(infoIDX)) + { + return; + } + + // + data[infoIDX].ticket = signal.positionId; + + // + // Find Orders for Accessing Commission ... + XDeal deals[]; + int dealsCount = mTrader.GetDeals( + deals, + signal.symbol, + signal.provider, + signal.period, + NULL, + DEAL_ENTRY_IN // Position Open Deal ... + ); + if (!IsValidSize(dealsCount)) + { + return; + } + + // + for (int i = 0; i < dealsCount; i++) + { + // + XDeal iDeal = deals[i]; + + // + if (iDeal.positionId == signal.positionId) + { + data[infoIDX].commission = iDeal.commission; + } + } + + // + // Check if Grid System Enable or Not ... + if (EnableGrid()) + { + // + // Here we Prepare Handler Structure for + // Next Grid Position ... + data[infoIDX].PrepareNextGrid( + GridDistance(), + GridVolumeMultiplier() // + ); + } + + // + // Check if Recovery System Enable or Not ... + if (EnableRecovery()) + { + // + data[infoIDX].PrepareNextRecovery( + GridDistance(), + GridVolumeMultiplier(), + signal.type // + ); + } + } + + // + void Update(XDeal &deal) + { + // + if (!deal.IsValid()) + { + return; + } + + // + int infoIDX = FindIndex(deal.positionId); + if (!IsValidIndex(infoIDX)) + { + return; + } + + // + data[infoIDX].swap = deal.swap; + data[infoIDX].endTime = deal.time; + data[infoIDX].profit = deal.profit; + + // + string message = deal.reason == DEAL_REASON_TP + ? "TP" + : "SL"; + data[infoIDX].message = message; + + // + Finish(infoIDX); + } + + // + void Update(XPosition &position) + { + // + if (!position.IsValid()) + { + return; + } + + // + int infoIDX = FindIndex(position.ticket); + if (!IsValidIndex(infoIDX)) + { + return; + } + + // + data[infoIDX].swap = position.swap; + data[infoIDX].endTime = TimeCurrent(); + data[infoIDX].profit = position.profit; + data[infoIDX].message = position.comment; + + // + Finish(infoIDX); + } + + // + bool AllowToGrid( + XSignal &signal // + ) + { + // + bool result = false; + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + int infoIDX = FindIndex(signal); + result = IsValidIndex(infoIDX); + if (!result) + { + return result; + } + + // + data[infoIDX].allowGrid = true; + data[infoIDX].PrepareNextGrid( + GridDistance(), + GridVolumeMultiplier() // + ); + + // + return result; + } + + // + bool AllowToRecovery( + XSignal &signal // + ) + { + // + bool result = false; + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + int infoIDX = FindIndex(signal); + result = IsValidIndex(infoIDX); + if (!result) + { + return result; + } + + // + data[infoIDX].allowRecover = true; + data[infoIDX].PrepareNextRecovery( + GridDistance(), + GridVolumeMultiplier(), + signal.type // + ); + + // + return result; + } + + // + // Sync ... + void Sync() + { + // + int count = Count(); + if (!IsValidSize(count)) + { + return; + } + + // + int mustRemoved[]; + for (int i = 0; i < count; i++) + { + // + XTradeInfo iInfo = data[i]; + + // + if (iInfo.ticket > 0 && !mTrader.IsOpen(iInfo.ticket)) + { + // + AddSpecific( + i, + mustRemoved // + ); + } + } + + // + int mustRemovedCount = ArraySize(mustRemoved); + if (!IsValidSize(mustRemovedCount)) + { + return; + } + + // + for (int i = 0; i < mustRemovedCount; i++) + { + // + ArrayRemove( + data, + i, + 1 // + ); + } + } + + // + // Protection Handlers ... + + // + // Handle Do All Protecting ... + int DoProtect( + XSignal &signals[], // if PRotecting Generate Some Support Signals, Holds them here + XSCX121SetupCycles *&setups[] // Number of Setups + ) + { + // + int result = 0; + + // + // Calling Protection Algorithms ... + + // + // Trailling ... + if (EnableTrailling()) + { + int traillings = HandleTrailling(); + } + + // + if (AllowSupport()) + { + // + XSignal supports[]; + int supportsCount = RequestForSupport( + supports, + setups // + ); + + // + if (IsValidSize(supportsCount)) + { + // + Copy( + supports, + signals, + false // + ); + } + } + + // + // Grid ... + if (EnableGrid()) + { + // + XSignal grids[]; + int gridsCount = RequestForGrid(grids); + if (IsValidSize(gridsCount)) + { + // + Copy( + grids, + signals, + false // + ); + } + } + + // + // Recovery ... + if (EnableRecovery()) + { + // + XSignal recoveries[]; + int recoveriesCount = RequestForRecovery(recoveries); + if (IsValidSize(recoveriesCount)) + { + // + Copy( + recoveries, + signals, + false // + ); + } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + int GetBreakoutsSignals(XSignal &signals[]) + { + // + int result = 0; + + // + Clean(signals); + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + double iEntry = data[i].entry; + string iSymbol = data[i].symbol; + ENUM_TIMEFRAMES iPeriod = data[i].period; + ENUM_X_POSITION_TYPES iType = data[i].type; + + // + bool isLong = IsLong(iType); + ENUM_POSITION_TYPE iPType = isLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + double cEntry = GetEntry( + iSymbol, + iPType // + ); + + // + XOHCL cBar; + bool isInited = cBar.Init( + iSymbol, + iPeriod, + 1 // + ); + if (!isInited) + { + continue; + } + + // + bool isBullish = cBar.IsBullish(); + bool isBreakUp = cBar.IsBreakUp(iEntry); + + // + bool isBearish = cBar.IsBearish(); + bool isBreakDown = cBar.IsBreakDown(iEntry); + + // + bool isBreaked = + isLong + ? isBullish && isBreakUp && cEntry > iEntry + : isBearish && isBreakDown && cEntry < iEntry; + + // + if (isBreaked) + { + // + // Update Date of TradeInfo ... + data[i].entry = cEntry; + data[i].time = TimeCurrent(); + + // + // Generate Signal ... + XSignal iSignal; + bool isPrepared = iSignal.Prepare( + data[i].symbol, + data[i].provider, + data[i].period, + iPType, + X_ORDER_MODE_MARKET, + data[i].entry, + data[i].volume, + 0, + 0 // + ); + + // + // Add Signal to Result ... + if (isPrepared) + { + // + AddRef( + iSignal, + signals // + ); + } + } + + // // + // double hotLevels[]; + + // // + // AddSpecific( + // 0.25, + // hotLevels // + // ); + + // // + // AddSpecific( + // 0.20, + // hotLevels // + // ); + + // // + // AddSpecific( + // 0.12, + // hotLevels // + // ); + + // // + // XSCZonesInput zonesInput; + // zonesInput.length = 71; + // zonesInput.numberOfZones = 10; + // XSCZones *zones = new XSCZones( + // iSymbol, + // _Period // + // ); + + // // + // zonesInput.AddLevelColor( + // hotLevels[0], + // clrRed // + // ); + // zonesInput.AddLevelColor( + // hotLevels[1], + // clrOrange // + // ); + // zonesInput.AddLevelColor( + // hotLevels[2], + // clrLightCoral // + // ); + // bool canUseZones = zones.Init(zonesInput); + + // // + // XSCCFInput cfInputs; + // cfInputs.Default(); + // XSCCF *cf = new XSCCF( + // iSymbol, + // _Period // + // ); + // bool canUseCF = cf.Init(cfInputs); + + // // + // XSCTrendInput tInputs; + // tInputs.Default(); + // XSCTrend *trend = new XSCTrend( + // iSymbol, + // _Period // + // ); + // bool canUseTrend = trend.Init(tInputs); + + // if (canUseCF && canUseTrend && canUseZones) + // { + // // + // // cf.Draw(); + // trend.Draw(); + // // zones.Draw(); + // Print("Use CF ..."); + // // cf.Remove(); + // // trend.Remove(); + // // zones.Remove(); + // } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + // Protected ... +protected: + // + // Props ... + XSCTrade *mTrader; + XTradeInfo data[]; + XTradeInfoCollector *collector; + + // + bool mSave; // Save Results ... + bool mSaveSignalsOnly; // Save Only Signals and COnditions + + // + // Hedging ... + double mMinProfitPerTrade; // Minimum Required Profit for Hedging + double mMinProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Volume + + // + // Trailling ... + bool mAllowTrailStop; // Enable Trailling Stop Losses + bool mDisableTrailingWhenOpposit; // Disable Trailling When has Opposite In Drawdown + double mNextTrailPoint; // Next Trailling Step + double mFirstTrailPoint; // First Stop Trail + double mFirstTrailDistance; // Start Trailling Distance + double mNextTrailDistance; // Next Trailling Distance + + // + // Supporting ... + bool mAllowSupport; // Allow Support Signals + bool mSupportOnlyForces; // Support Only Force Signals + double mSupportDistance; // Supporting Distance + int mMaxNumberOfSupports; // Max Number of Support Signals + double mSupportVolumeMultiplier; // Support Signals Volume Multiplier + double mMaxAllowedSupportVolume; // Max Allowed Support Signals Volume + + // + // Grid ... + bool mAllowGrid; // Allow Grid Signals + bool mGridOnlyForces; // Grid Only Force Signals + int mMaxNumberOfGrids; // Max Number of Grid Signals + double mGridDistance; // Grid Distance + double mGridVolumeMultiplier; // Grid Volume Multiplier + double mMaxAllowedGridVolume; // Max Allowed Grid Signals Volume + + // + // Recovery ... + bool mAllowRecovery; // Allow Recovery Signals + bool mRecoverOnlyForces; // Recover Only Force Signals + int mMaxNumberOfRecoveries; // Max Number of Recovery Signals + double mRecoveryDistance; // Recovery Distance + double mRecoveryVolumeMultiplier; // Recovery Volume Multiplier + double mMaxAllowedRecoveryVolume; // Max Allowed Recovery Signals Volume + + // + // Tools ... + + // + void Finish(int index) + { + // + XTradeInfo info = data[index]; + if (!info.IsValid()) + { + return; + } + + // + ArrayRemove( + data, + index, + 1 // + ); + + // + if (GetSave()) + { + collector.Save(info); + } + } + + // + // Protection Methods ... + + // + int HandleTrailling() + { + // + int result = 0; + + // + // Check Trailling is Enabled or not ... + if (!EnableTrailling()) + { + return result; + } + + // + // Do Synch Before Start Trailing ... + Sync(); + + // + // Since Trailing Done based On In Profit Positions ... + // First we Check if ... + XPosition positions[]; + XPosition inDPositions[]; + XPosition inPPositions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + int inDPositionsCount = ExtractInDrawdownPositions( + positions, + inDPositions // + ); + int inPPositionsCount = ExtractInProfitPositions( + positions, + inPPositions // + ); + if (!IsValidSize(inPPositionsCount)) + { + return result; + } + + // + for (int i = 0; i < inPPositionsCount; i++) + { + // + XPosition iPosition = inPPositions[i]; + + // + // ignore Support Positions ... + bool isSupport = IsSupport(iPosition.comment); + if (isSupport) + { + continue; + } + + // + // Only Trail Positions which they Hasnt any Support ... + bool hasSupport = mTrader.HasSupport(iPosition.ticket); + result = !hasSupport; + if (!result) + { + return result; + } + + // + // Find Positin Info Index ... + int idx = FindIndex(iPosition.ticket); + if (!IsValidIndex(idx)) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + + // + // Here we Select Price for SL Trailling ... + double usedPrice = 0; + if (iPosition.sl != 0) + { + // + if (isLong) + { + // + if (iPosition.sl < iPosition.entry) + { + usedPrice = iPosition.entry; + } + else + { + usedPrice = iPosition.sl; + } + } + else + { + // + if (iPosition.sl > iPosition.entry) + { + usedPrice = iPosition.entry; + } + else + { + usedPrice = iPosition.sl; + } + } + } + else + { + usedPrice = iPosition.entry; + } + + // + double nextTrailPoint = NextTrailPoint(); + double firstTrailPoint = FirstTrailPoint(); + double nextTrailDistance = NextTrailDistance(); + double firstTrailDistance = FirstTrailDistance(); + + // + bool isFirstTrail = usedPrice == iPosition.entry; + + // + double usedTrailDiff = + isFirstTrail + ? MathMax(firstTrailPoint, firstTrailDistance) + : MathMax(nextTrailPoint, nextTrailDistance); + + // + double iExit = GetExit( + iPosition.symbol, + iPosition.type // + ); + double iPriceDistance = MathAbs(usedPrice - iExit); + double iPriceDistanceInPoint = PriceToPoint( + iPriceDistance, + iPosition.symbol // + ); + + // + bool canTrail = iPriceDistanceInPoint >= usedTrailDiff; + if (!canTrail) + { + continue; + } + + // + // Check Opposit Side Position ... + // if Exists, dont Trail ... + if (DisableTrailingWhenOpposit() && IsValidSize(inDPositionsCount)) + { + // + bool canTrail = true; + ENUM_POSITION_TYPE oppositType = GetOpposit(iPosition.type); + for (int j = 0; j < inDPositionsCount; j++) + { + // + XPosition inDPosition = inDPositions[j]; + + // + bool isOpposit = + inDPosition.symbol == iPosition.symbol && + inDPosition.type == oppositType; + if (isOpposit) + { + // + canTrail = false; + break; + } + } + + // + if (!canTrail) + { + continue; + } + } + + // + usedTrailDiff = + isFirstTrail + ? MathMin(firstTrailPoint, firstTrailDistance) + : MathMin(nextTrailPoint, nextTrailDistance); + double usedTrailDiffPrice = PointToPrice( + usedTrailDiff, + iPosition.symbol // + ); + + // + double sl = + isLong + ? usedPrice + usedTrailDiffPrice + : usedPrice - usedTrailDiffPrice; + string comment = PrepareSLTrailTag(iPosition.comment); + + // + bool isModified = mTrader.Modify( + iPosition.ticket, + sl, + iPosition.tp, + comment // + ); + if (isModified) + { + result++; + } + } + + // + return result; + } + + // + int RequestForSupport( + XSignal &signals[], + XSCX121SetupCycles *&setups[] // + ) + { + // + int result = 0; + + // + Clean(signals); + + // + if (!AllowSupport()) + { + return result; + } + + // + Sync(); + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSignal iSupport; + double iPivot = -1; + int iPivotIDX = -1; + bool hasSupport = data[i].HasSupport( + iSupport // + ); + if (hasSupport) + { + // + AddRef( + iSupport, + signals // + ); + } + } + + // + result = ArraySize(signals); + + // + // TODO: Complete this Later ... + return result; + + // + // Validate Setups Count ... + // int setupsCount = ArraySize(setups); + // if (!IsValidSize(setupsCount)) + // { + // return result; + // } + + // // + // // Implement Supporting Mechanism ... + + // // + // // Extracting In Drawdown Positions ... + // XPosition positions[]; + // int positionsCount = mTrader.GetInDrawdownPositions( + // positions // + // ); + // if (!IsValidSize(positionsCount)) + // { + // return result; + // } + + // // + // double supportDistance = SupportDistance(); + // int maxNUmberOfSupports = MaxNumberOfSupports(); + // double maxAllowedVolume = MaxAllowedSupportVolume(); + // double volumeMultiplier = SupportVolumeMultiplier(); + + // // + // X121SignalGenerator signalGenerator; + + // // + // for (int i = 0; i < positionsCount; i++) + // { + // // + // XPosition iPosition = positions[i]; + + // // + // // Check Position is not Support Position ... + // bool isSupport = IsSupport(iPosition.comment); + // if (isSupport) + // { + // continue; + // } + + // // + // // Find Related Setp ... + // int idx = FindSetupIndex( + // iPosition.symbol, + // setups // + // ); + // if (!IsValidIndex(idx)) + // { + // continue; + // } + + // // + // int index = FindIndex(iPosition.ticket); + // if (!IsValidIndex(index)) + // { + // continue; + // } + + // // + // // Check Position must atleast 20 Point in drawdown ... + + // // + // double onePointPrice = PointToPrice( + // 1, + // iPosition.symbol // + // ); + + // // + // double iExitPrice = GetExit( + // iPosition.symbol, + // iPosition.type // + // ); + + // // + // double priceDiff = MathAbs(iPosition.entry - iExitPrice); + // double priceDiffPoints = priceDiff / onePointPrice; + + // // + // bool isFarEnough = priceDiffPoints >= (supportDistance / 2); + // if (!isFarEnough) + // { + // continue; + // } + + // // + // // Check Support COunts and etc ... + // // implementing supporting mechanis ... + + // // + // } + + // // + // result = ArraySize(signals); + + // + return result; + } + + // + int RequestForGrid(XSignal &signals[]) + { + // + int result = 0; + + // + Clean(signals); + + // + if (!EnableGrid()) + { + return result; + } + + // + int maxAllowed = MaxNumberOfGrids(); + double maxAllowedVolume = MaxAllowedGridVolume(); + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + // Check Count ... + bool isMaxPassed = + maxAllowed <= 0 + ? true + : data[i].gLevel < maxAllowed; + if (!isMaxPassed) + { + continue; + } + + // + XSignal iSignal; + bool hasGrid = data[i].HasGrid( + iSignal, + GridDistance(), + GridVolumeMultiplier() // + ); + + // + if (hasGrid) + { + // + // Check Max Volume ... + iSignal.volume = + maxAllowedVolume <= 0 + ? iSignal.volume + : MathMin(iSignal.volume, maxAllowedVolume); + + // + AddRef( + iSignal, + signals // + ); + } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + int RequestForRecovery(XSignal &signals[]) + { + // + int result = 0; + + // + Clean(signals); + + // + if (!EnableRecovery()) + { + return result; + } + + // + int maxAllowed = MaxNumberOfRecoveries(); + double maxAllowedVolume = MaxAllowedRecoveryVolume(); + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + // Check Count ... + bool isMaxPassed = + maxAllowed <= 0 + ? true + : data[i].rLevel < maxAllowed; + if (!isMaxPassed) + { + continue; + } + + // + XSignal iSignal; + bool hasRecovery = data[i].HasRecovery( + iSignal, + RecoveryDistance(), + RecoveryVolumeMultiplier() // + ); + + // + if (hasRecovery) + { + // + // Check Max Volume ... + iSignal.volume = + maxAllowedVolume <= 0 + ? iSignal.volume + : MathMin(iSignal.volume, maxAllowedVolume); + + // + AddRef( + iSignal, + signals // + ); + } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + int FindSetupIndex( + string symbol, + XSCX121SetupCycles *&setups[] // + ) + { + // + int result = 0; + + // + if (!IsValid(symbol)) + { + return result; + } + + // + for (int i = 0; i < ArraySize(setups); i++) + { + // + if (setups[i].GetSymbol() == symbol) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + void AddHotLevelsToZones( + XSCZones *zones // + ) + { + // + zones.AddLevelColor( + 0.25, + clrRed // + ); + zones.AddLevelColor( + 0.20, + clrOrange // + ); + zones.AddLevelColor( + 0.15, + clrYellow // + ); + } +}; + +// +// Class ... +class XSCX121SetupEA : public XSCBaseEA +{ + // + // Public ... +public: + // + // Props ... + X121SignalGenerator signalGenerator; + + // + // Constructors ... + XSCX121SetupEA( + // + // 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 // + ) + { + // + mTradeHandler = new XTradeHandler(mTrader); + + // + // Implement Default Configs ... + DefaultConfigs(); + } + + // + // Deconstructor ... + ~XSCX121SetupEA() + { + // + delete mTradeHandler; + + // + Clean(mSetups); + } + + // + bool AddSetup(XSCX121SetupCycles *setup) + { + // + bool result = false; + + // + result = setup != NULL; + if (!result) + { + return result; + } + + // + Add( + setup, + mSetups // + ); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + /// Signals ... + + // + bool AllowLong() + { + return mAllowLong; + } + + // + void AllowLong(bool value) + { + mAllowLong = value; + } + + // + bool AllowShort() + { + return mAllowShort; + } + + // + void AllowShort(bool value) + { + mAllowShort = value; + } + + // + int DelayBetweenTwoSignal() + { + return mDelayBetweenTwoSignal; + } + + // + void DelayBetweenTwoSignal(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDelayBetweenTwoSignal = value; + } + + // + int ReuiredSignalVerifications() + { + return mReuiredSignalVerifications; + } + + // + void ReuiredSignalVerifications(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mReuiredSignalVerifications = value; + } + + // + bool GetVerificationFromOtherTimeFrames() + { + return mGetVerificationFromOtherTimeFrames; + } + + // + void GetVerificationFromOtherTimeFrames(bool value) + { + mGetVerificationFromOtherTimeFrames = value; + } + + // + bool ExecuteSignalsOnBreakout() + { + return mExecuteSignalsOnBreakout; + } + + // + void ExecuteSignalsOnBreakout(bool value) + { + mExecuteSignalsOnBreakout = value; + } + + // + // Risk Management ... + + // + double Volume() + { + return mVolume; + } + + // + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + double TPPoint() + { + return mTPPoint; + } + + // + void TPPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mTPPoint = value; + } + + // + double SLPoint() + { + return mSLPoint; + } + + // + void SLPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSLPoint = value; + } + + // + int MaxAllowedTrades() + { + return mMaxAllowedTrades; + } + + // + void MaxAllowedTrades(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedTrades = value; + // mTrader.SetMaxAllowedPositions(value); + } + + // + bool UseMaxAllowedPerDirection() + { + return mUseMaxAllowedPerDirection; + } + + // + void UseMaxAllowedPerDirection(bool value) + { + mUseMaxAllowedPerDirection = value; + } + + // + bool IgnoreTP() + { + return mIgnoreTP; + } + + // + void IgnoreTP(bool value) + { + mIgnoreTP = value; + } + + // + bool IgnoreSL() + { + return mIgnoreSL; + } + + // + void IgnoreSL(bool value) + { + mIgnoreSL = value; + } + + // + // Signalling ... + + // + int StartSignallingHoure() + { + return mStartSignallingHoure; + } + + // + void StartSignallingHoure(int value) + { + // + if (value < -1) + { + value = -1; + } + + // + mStartSignallingHoure = value; + } + + // + int EndSignallingHoure() + { + return mEndSignallingHoure; + } + + // + void EndSignallingHoure(int value) + { + // + if (value < -1) + { + value = -1; + } + + // + mEndSignallingHoure = value; + } + + // + int CloseOnSpecificTime() + { + return mCloseOnSpecificTime; + } + + // + void CloseOnSpecificTime(int value) + { + // + if (value < -1) + { + value = -1; + } + + // + mCloseOnSpecificTime = value; + } + + // + bool CloseOnOpposit() + { + return mCloseOnOpposit; + } + + // + void CloseOnOpposit(bool value) + { + mCloseOnOpposit = value; + } + + // + // Trailling ... + + // + bool AllowTrailStop() + { + return mTradeHandler.AllowTrailStop(); + } + + // + void AllowTrailStop(bool value) + { + mTradeHandler.AllowTrailStop(value); + } + + // + bool DisableTrailingWhenOpposit() + { + return mTradeHandler.DisableTrailingWhenOpposit(); + } + + // + void DisableTrailingWhenOpposit(bool value) + { + mTradeHandler.DisableTrailingWhenOpposit(value); + } + + // + double NextTrailPoint() + { + return mTradeHandler.NextTrailPoint(); + } + + // + void NextTrailPoint(double value) + { + mTradeHandler.NextTrailPoint(value); + } + + // + double FirstTrailPoint() + { + return mTradeHandler.FirstTrailPoint(); + } + + // + void FirstTrailPoint(double value) + { + mTradeHandler.FirstTrailPoint(value); + } + + // + double NextTrailDistance() + { + return mTradeHandler.NextTrailDistance(); + } + + // + void NextTrailDistance(double value) + { + mTradeHandler.NextTrailDistance(value); + } + + // + double FirstTrailDistance() + { + return mTradeHandler.FirstTrailDistance(); + } + + // + void FirstTrailDistance(double value) + { + mTradeHandler.FirstTrailDistance(value); + } + + // + // Supporting ... + + // + bool AllowSupport() + { + return mTradeHandler.AllowSupport(); + } + + // + void AllowSupport(bool value) + { + mTradeHandler.AllowSupport(value); + } + + // + bool SupportOnlyForces() + { + return mTradeHandler.SupportOnlyForces(); + } + + // + void SupportOnlyForces(bool value) + { + mTradeHandler.SupportOnlyForces(value); + } + + // + bool EnableSupport() + { + return mTradeHandler.EnableSupport(); + } + + // + double SupportDistance() + { + return mTradeHandler.SupportDistance(); + } + + // + void SupportDistance(double value) + { + mTradeHandler.SupportDistance(value); + } + + // + int MaxNumberOfSupports() + { + return mTradeHandler.MaxNumberOfSupports(); + } + + // + void MaxNumberOfSupports(int value) + { + mTradeHandler.MaxNumberOfSupports(value); + } + + // + double SupportVolumeMultiplier() + { + return mTradeHandler.SupportVolumeMultiplier(); + } + + // + void SupportVolumeMultiplier(double value) + { + mTradeHandler.SupportVolumeMultiplier(value); + } + + // + double MaxAllowedSupportVolume() + { + return mTradeHandler.MaxAllowedSupportVolume(); + } + + // + void MaxAllowedSupportVolume(double value) + { + mTradeHandler.MaxAllowedSupportVolume(value); + } + + // + // Grid ... + + // + bool AllowGrid() + { + return mTradeHandler.AllowGrid(); + } + + // + void AllowGrid(bool value) + { + mTradeHandler.AllowGrid(value); + } + + // + bool GridOnlyForces() + { + return mTradeHandler.GridOnlyForces(); + } + + // + void GridOnlyForces(bool value) + { + mTradeHandler.GridOnlyForces(value); + } + + // + bool EnableGrid() + { + return mTradeHandler.EnableGrid(); + } + + // + int MaxNumberOfGrids() + { + return mTradeHandler.MaxNumberOfGrids(); + } + + // + void MaxNumberOfGrids(int value) + { + mTradeHandler.MaxNumberOfGrids(value); + } + + // + double GridDistance() + { + return mTradeHandler.GridDistance(); + } + + // + void GridDistance(double value) + { + mTradeHandler.GridDistance(value); + } + + // + double GridVolumeMultiplier() + { + return mTradeHandler.GridVolumeMultiplier(); + } + + // + void GridVolumeMultiplier(double value) + { + mTradeHandler.GridVolumeMultiplier(value); + } + + // + double MaxAllowedGridVolume() + { + return mTradeHandler.MaxAllowedGridVolume(); + } + + // + void MaxAllowedGridVolume(double value) + { + mTradeHandler.MaxAllowedGridVolume(value); + } + + // + // Recovery System ... + + // + bool AllowRecovery() + { + return mTradeHandler.AllowRecovery(); + } + + // + void AllowRecovery(bool value) + { + mTradeHandler.AllowRecovery(value); + } + + // + bool RecoverOnlyForces() + { + return mTradeHandler.RecoverOnlyForces(); + } + + // + void RecoverOnlyForces(bool value) + { + mTradeHandler.RecoverOnlyForces(value); + } + + // + bool EnableRecovery() + { + return mTradeHandler.EnableRecovery(); + } + + // + int MaxNumberOfRecoveries() + { + return mTradeHandler.MaxNumberOfRecoveries(); + } + + // + void MaxNumberOfRecoveries(int value) + { + mTradeHandler.MaxNumberOfRecoveries(value); + } + + // + double RecoveryDistance() + { + return mTradeHandler.RecoveryDistance(); + } + + // + void RecoveryDistance(double value) + { + mTradeHandler.RecoveryDistance(value); + } + + // + double RecoveryVolumeMultiplier() + { + return mTradeHandler.RecoveryVolumeMultiplier(); + } + + // + void RecoveryVolumeMultiplier(double value) + { + mTradeHandler.RecoveryVolumeMultiplier(value); + } + + // + double MaxAllowedRecoveryVolume() + { + return mTradeHandler.MaxAllowedRecoveryVolume(); + } + + // + void MaxAllowedRecoveryVolume(double value) + { + mTradeHandler.MaxAllowedRecoveryVolume(value); + } + + // + // Others ... + + // + bool SaveResults() + { + return mTradeHandler.GetSave(); + } + + // + void SaveResults(bool value) + { + mTradeHandler.SetSave(value); + } + + // + bool SaveSignalsOnly() + { + return mTradeHandler.GetSaveSignalsOnly(); + } + + // + void SaveSignalsOnly(bool value) + { + mTradeHandler.SetSaveSignalsOnly(value); + } + + // + double MinFreeMargingForOpenTrades() + { + return mMinFreeMargingForOpenTrades; + } + + // + void MinFreeMargingForOpenTrades(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinFreeMargingForOpenTrades = value; + } + + // + // Hedging ... + + // + double MinProfitPerTrade() + { + return mTradeHandler.MinProfitPerTrade(); + } + + // + void MinProfitPerTrade(double value) + { + // + MinRequiredProfitPerTrade(value); + mTradeHandler.MinProfitPerTrade(value); + } + + // + double MinProfitPerVolumeFactor() + { + return mTradeHandler.MinProfitPerVolumeFactor(); + } + + // + void MinProfitPerVolumeFactor(double value) + { + // + MinRequiredProfitPerVolumeFactor(value); + mTradeHandler.MinProfitPerVolumeFactor(value); + } + + // + // Overrides ... + + // + // Customize Token ... + string GetToken() override + { + return GetSpecificToken(this); + } + + // + string GetTag() override + { + return this.GetToken(); + } + + // + // Tools ... + + // + // Check Provider for any Guards ... + bool CheckForGuard(XGuard &guards[]) override + { + // + bool result = false; + + // + return result; + } + + // + // Request Provider to Collect all + // Potentially Signals and then + // filters theme here and passed them + // for Executing ... + int RequestForSignal( + XSignal &signals[] // Holds Signals ... + ) override + { + // + bool result = 0; + + // + Clean(signals); + + // + if (!IsEnable()) + { + return result; + } + + // + // IMPLEMENT ... + int count = CountSetups(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // Current ... + double cTP = 0; + double cSL = 0; + XSignal cSignal; + int cPusher = 0; + bool cHasSignal = false; + string cProvider = NULL; + X121SetupConditions cConditions; + + // + // Short ... + double sTP = 0; + double sSL = 0; + XSignal sSignal; + int sPusher = 0; + bool sHasSignal = false; + string sProvider = NULL; + X121SetupConditions sConditions; + + // + // Medium ... + double mTP = 0; + double mSL = 0; + XSignal mSignal; + int mPusher = 0; + bool mHasSignal = false; + string mProvider = NULL; + X121SetupConditions mConditions; + + // + // Long ... + double lTP = 0; + double lSL = 0; + XSignal lSignal; + int lPusher = 0; + bool lHasSignal = false; + string lProvider = NULL; + X121SetupConditions lConditions; + + // + // Hind ... + double hTP = 0; + double hSL = 0; + XSignal hSignal; + int hPusher = 0; + bool hHasSignal = false; + string hProvider = NULL; + X121SetupConditions hConditions; + + // + bool canSupport = + // + EnableSupport() && + !SupportOnlyForces() + // + ; + bool canGrid = + // + EnableGrid() && + !GridOnlyForces() + // + ; + bool canRecover = + // + EnableRecovery() && + !RecoverOnlyForces() + // + ; + + // + double volume = Volume(); + double slPoint = SLPoint(); + double tpPoint = TPPoint(); + bool ignoreSL = IgnoreSL(); + bool ignoreTP = IgnoreTP(); + bool allowLong = AllowLong(); + bool allowShort = AllowShort(); + + // + bool useCMarket = true; + bool useSMarket = true; + bool useMMarket = true; + bool useLMarket = true; + bool useHMarket = true; + + // + for (int i = 0; i < count; i++) + { + // + // Current Market ... + + // + cPusher = 0; + cSignal.Clean(); + cProvider = NULL; + cHasSignal = false; + cConditions.Clean(); + + // + cHasSignal = !useCMarket + ? false + : mSetups[i] + .ProcessMarket( + cSignal, + cConditions, + cPusher, + cProvider, + cTP, + cSL, + X_MARKET_CYCLE_UNKNOWN, + canSupport, + allowLong, + allowShort, + volume, + slPoint, + ignoreSL, + tpPoint, + ignoreTP, + 0, + 5 // + ); + + // + // Short Market ... + + // + sPusher = 0; + sSignal.Clean(); + sProvider = NULL; + sHasSignal = false; + sConditions.Clean(); + + // + sHasSignal = !useSMarket + ? false + : mSetups[i] + .ProcessMarket( + sSignal, + sConditions, + sPusher, + sProvider, + sTP, + sSL, + X_MARKET_CYCLE_SHORT, + canSupport, + allowLong, + allowShort, + volume, + slPoint, + ignoreSL, + tpPoint, + ignoreTP, + 0, + 5 // + ); + + // + // Medium Market ... + + // + mPusher = 0; + mSignal.Clean(); + mProvider = NULL; + mHasSignal = false; + mConditions.Clean(); + + // + mHasSignal = !useMMarket + ? false + : mSetups[i] + .ProcessMarket( + mSignal, + mConditions, + mPusher, + mProvider, + mTP, + mSL, + X_MARKET_CYCLE_MEDIUM, + canSupport, + allowLong, + allowShort, + volume, + slPoint, + ignoreSL, + tpPoint, + ignoreTP, + 0, + 5 // + ); + + // + // Long Market ... + + // + lPusher = 0; + lSignal.Clean(); + lProvider = NULL; + lHasSignal = false; + lConditions.Clean(); + + // + lHasSignal = !useLMarket + ? false + : mSetups[i] + .ProcessMarket( + lSignal, + lConditions, + lPusher, + lProvider, + lTP, + lSL, + X_MARKET_CYCLE_LONG, + canSupport, + allowLong, + allowShort, + volume, + slPoint, + ignoreSL, + tpPoint, + ignoreTP, + 0, + 5 // + ); + + // + // Hind Market ... + + // + hPusher = 0; + hSignal.Clean(); + hProvider = NULL; + hHasSignal = false; + hConditions.Clean(); + + // + hHasSignal = !useHMarket + ? false + : mSetups[i] + .ProcessMarket( + hSignal, + hConditions, + hPusher, + hProvider, + hTP, + hSL, + X_MARKET_CYCLE_HIND, + canSupport, + allowLong, + allowShort, + volume, + slPoint, + ignoreSL, + tpPoint, + ignoreTP, + 0, + 5 // + ); + + // + // Parse Signals and Add them for Executing ... + + // + // Check if there is a Signal or Not ... + bool hasSignal = cHasSignal || sHasSignal || mHasSignal || lHasSignal || hHasSignal; + if (hasSignal) + { + // + XSignal signal; + X121SetupConditions otherConditions[]; + + // + if (cHasSignal) + { + // + signal = cSignal; + + // + AddRef( + sConditions, + otherConditions // + ); + AddRef( + mConditions, + otherConditions // + ); + // AddRef( + // lConditions, + // otherConditions // + // ); + // AddRef( + // hConditions, + // otherConditions // + // ); + } + + // + if (sHasSignal) + { + // + signal = sSignal; + + // + AddRef( + cConditions, + otherConditions // + ); + AddRef( + mConditions, + otherConditions // + ); + // AddRef( + // lConditions, + // otherConditions // + // ); + // AddRef( + // hConditions, + // otherConditions // + // ); + } + + // + if (mHasSignal) + { + // + signal = mSignal; + + // + AddRef( + sConditions, + otherConditions // + ); + AddRef( + lConditions, + otherConditions // + ); + } + + // + if (lHasSignal) + { + // + signal = lSignal; + + // + // AddRef( + // cConditions, + // otherConditions // + // ); + AddRef( + mConditions, + otherConditions // + ); + AddRef( + hConditions, + otherConditions // + ); + } + + // + if (hHasSignal) + { + // + signal = hSignal; + + // + AddRef( + cConditions, + otherConditions // + ); + AddRef( + sConditions, + otherConditions // + ); + AddRef( + mConditions, + otherConditions // + ); + AddRef( + lConditions, + otherConditions // + ); + AddRef( + hConditions, + otherConditions // + ); + } + + // + int pushers = cPusher + sPusher + mPusher + lPusher + hPusher; + + // + bool isLong = IsLong(signal.type); + + // + // Validate Signal ... + bool isValid = + // + // Handle Pusher Validations ... + (mReuiredSignalVerifications <= 0 + ? true + : pushers >= mReuiredSignalVerifications) + // + && + // + // Handle Other Conditions Validations ... + (!mGetVerificationFromOtherTimeFrames + ? true + : isLong + ? signalGenerator.HasLongVerifications(otherConditions) + : signalGenerator.HasShortVerifications(otherConditions)) + // + ; + + // + bool forceState = mForce; // mSetups[i].ForceState(); + + // + if (!forceState) + { + // + // Add Signal to Execution Result ... + AddRef( + signal, + signals // + ); + + // + // Add new Signal Info ... + mTradeHandler.Add( + signal, + pushers, + canGrid, + canRecover, + canSupport, + cConditions, + sConditions, + mConditions, + lConditions, + hConditions // + ); + } + else + { + // + // Clear Other Conditions ... + Clean(otherConditions); + + // + // Fill All Conditions to Other Conditions ... + AddRef( + cConditions, + otherConditions // + ); + AddRef( + sConditions, + otherConditions // + ); + AddRef( + mConditions, + otherConditions // + ); + AddRef( + lConditions, + otherConditions // + ); + AddRef( + hConditions, + otherConditions // + ); + + // + // If Recieved Any Unverified Signal + // we Passed it to EQM Manager ... + EQMHandleInvalidSignal( + signal, + pushers, + isValid, + otherConditions // + ); + } + } + } + + // + result = ArraySize(signals); + + // + return result; + } + + // + // Here we Manage Signals for Executing ... + // - Check Policies based on their Signaller ... + // - Check Same Time Open Positions ... + // - Check Signal Age for new Trade ... + // and etc ... + int HandleSignalManagement(XSignal &signals[]) override + { + // + int result = 0; + + // + int signalsCount = ArraySize(signals); + if (!IsValidSize(signalsCount)) + { + return result; + } + + // + XSignal tmpSignals[]; + XSignal eSignals[]; // Must Executed + Copy( + signals, + tmpSignals // + ); + + // + Clean(signals); + + // + int maxAllowed = MaxAllowedTrades(); + bool perDirection = UseMaxAllowedPerDirection(); + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = tmpSignals[i]; + + // + bool isSignalValid = false; + + // + isSignalValid = IsSignalDelayPassed(iSignal); + if (!isSignalValid) + { + continue; + } + + // + // Handle Close All Positions when Opposit Signal Recieved ... + if (mCloseOnOpposit) + { + // + // Select Signal Opposit Positions ... + ENUM_X_POSITION_TYPES iOpposit = GetOppositPositionType(iSignal.type); + + // + XPosition iPositions[]; + int iPositionsCount = mTrader.GetPositions( + iPositions, + iSignal.symbol, + NULL, // All Providers ... + NULL, // All Periods ... + iOpposit // Opposit Positions ... + ); + + // + if (IsValidSize(iPositionsCount)) + { + // + string comment = "Close due Opposit ..."; + + // + int closeds = Close( + iPositions, + comment // + ); + if (IsValidSize(closeds)) + { + // + string message = XEQMSupportToken + " Closed " + ToString(iPositionsCount) + " due Opposit Signal ..."; + + // + Alert(message); + } + } + } + + // + // TODO: Remove this ... + // isSignalValid = !AllowSupport() + // ? true + // : IsValidSize(ArraySize(iSignal.supports)); + // if (!isSignalValid) + // { + // continue; + // } + + // + // Filter Signals Based On Max Allowed ... + if (maxAllowed > 0) + { + // + // Here we Get Opposite Signals of Same Symbol Valid ... + ENUM_X_POSITION_TYPES iType = + perDirection + ? ToPositionType(iSignal.type) + : X_POSITION_TYPE_ALL; + XPosition iSymbolsPositions[]; + int iSymbolsPositionsCount = mTrader.GetPositions( + iSymbolsPositions, + iSignal.symbol, + NULL, // Provider + NULL, // Period + iType, // Type + true // + ); + + // + int iSupportsCount = 0; + if (IsValidSize(iSymbolsPositionsCount)) + { + // + // Filter Support Positions ... + XPosition iSupports[]; + iSupportsCount = ExtractSupports( + iSymbolsPositions, + iSupports // + ); + } + + // + isSignalValid = + iSupportsCount <= 0 + ? iSymbolsPositionsCount < maxAllowed + : iSymbolsPositionsCount - iSupportsCount < maxAllowed; + if (!isSignalValid) + { + continue; + } + } + else + { + isSignalValid = true; + } + + // + // Only Accept Next Same Type when Previous in Profit ... + if (isSignalValid) + { + // + ENUM_X_POSITION_TYPES iType = + ToPositionType(iSignal.type); + XPosition iSymbolsPositions[]; + int iSymbolsPositionsCount = mTrader.GetPositions( + iSymbolsPositions, + iSignal.symbol, + NULL, // Provider + NULL, // Period + iType, // Type + true // + ); + + // + int iSupportsCount = 0; + if (IsValidSize(iSymbolsPositionsCount)) + { + // + // Filter Support Positions ... + XPosition iSupports[]; + iSupportsCount = ExtractSupports( + iSymbolsPositions, + iSupports // + ); + + // + // Filter Support Positions ... + if (IsValidSize(iSupportsCount)) + { + // + XPosition tmpPositions[]; + Copy( + iSymbolsPositions, + tmpPositions // + ); + + // + Clean(iSymbolsPositions); + + // + for (int i = 0; i < iSymbolsPositionsCount; i++) + { + // + XPosition iPosition = tmpPositions[i]; + + // + bool isSupport = IsSupport(iPosition.comment); + if (isSupport) + { + continue; + } + + // + AddRef( + iPosition, + iSymbolsPositions // + ); + } + + // + iSymbolsPositionsCount = ArraySize(iSymbolsPositions); + } + } + + // + if (IsValidSize(iSymbolsPositionsCount)) + { + // + XPosition youngest; + int youngestAge = GetYoungest( + youngest, + iSymbolsPositions // + ); + + // + isSignalValid = youngest.profit > 0.1; + } + + // + if (!isSignalValid) + { + continue; + } + } + + // + // Multiply Signal Volume ... + if (isSignalValid) + { + // + XPosition iSymbolsPositions[]; + int iSymbolsPositionsCount = mTrader.GetPositions( + iSymbolsPositions, + iSignal.symbol, + NULL, // Provider + NULL, // Period + NULL, // Type + true // + ); + + // + int iSupportsCount = 0; + if (IsValidSize(iSymbolsPositionsCount)) + { + // + // Filter Support Positions ... + XPosition iSupports[]; + iSupportsCount = ExtractSupports( + iSymbolsPositions, + iSupports // + ); + } + + // + int multiplier = + iSupportsCount <= 0 + ? iSymbolsPositionsCount + : iSymbolsPositionsCount - iSupportsCount; + if (multiplier <= 0) + { + multiplier = 1; + } + else + { + multiplier++; + } + + // + // Ignore ... + iSignal.volume = iSignal.volume * multiplier; + } + + // + // Handle Signal ... + if (isSignalValid) + { + // + AddRef( + iSignal, + eSignals // + ); + } + } + + // + // Cutom Signal Execution ... + HandleSignals(eSignals); + + // + result = ArraySize(signals); + + // + return result; + } + + // + // Handle State Management .... + // here we can manage current state ... + // - Check for Long Positions for each Signaller to Close ... + // - Handle Hedging Signaller's Positions if it's enabled ... + // - Force Closing Position when Specified Time reached ... + // - Check Start and End time or Trading Dates ... + // - handle Trailing or Risk free Signals based on several conditions ... + // and etc ... + bool HandleStateManagement(XSignal &signals[]) override + { + // + const bool result = false; + + // + // Do all State Management here ... + + // + // Check if there are open Positions + // and their doesn't have TP and SL and + // Youngest Age of Positions longest as enough + // Make State of Signalling to Force State for Recieving + // Signal and Clear their Tp and SL for allowing hedges ... + // EQMHandleForceState(signals); + // if (mForce) + // { + // result = true; + // } + + // + DoHedge(); + + // + // Handle Close All Positions on Specific Time ... + DoEQMCloseOnSpecificTime(); + + // + // Do EQM Protection if Provided ... + DoEQMProtect(); + + // + // if Returns true, Signal Execution failed ... + return result; + } + + // + // Signal Info ... + + // + void OnSignalExecuted(const XSignal &signal) override + { + // + // Signal Info Manager ... + XSignal tSignal = signal; + bool isSupport = IsSupport(signal.comment); + if (!isSupport) + { + mTradeHandler.Update(tSignal); + } + + // + mTradeHandler.Sync(); + } + + // + void OnSignalExecutionFailed( + const XSignal &signal, + const ENUM_X_SIGNAL_EXECUTION_RESULT reason // + ) override + { + // + // Signal Info Manager ... + XSignal tSignal = signal; + mTradeHandler.Remove(tSignal); + mTradeHandler.Sync(); + } + + // + void OnPositionClosed( + const XPosition &position, + const string comment // + ) override + { + // + // When a Position Closed Manually ... + // Signal Info Manager ... + XPosition tPosition = position; + bool isSupport = ExtractSupportedTicket(position.comment) > 0; + bool isEQMSupport = ExtractEQMSupportedTicket(position.comment) > 0; + tPosition.comment = comment; + if (!isSupport && !isEQMSupport) + { + mTradeHandler.Update(tPosition); + } + + // + mTradeHandler.Sync(); + } + + // + void OnStopLossTriggered(const XDeal &deal) override + { + // + // When a Position's Stop Loss Triggered ... + // Signal Info Manager ... + XDeal tDeal = deal; + mTradeHandler.Update(tDeal); + mTradeHandler.Sync(); + } + + // + void OnTakeProfitTriggered(const XDeal &deal) override + { + // + // When a Position's Take Profit Triggered ... + // Signal Info Manager ... + XDeal tDeal = deal; + mTradeHandler.Update(tDeal); + mTradeHandler.Sync(); + } + + // + // Protected ... +protected: + // + // Tools ... + + // + // Check Signalling Enable or not ... + bool IsEnable() + { + // + bool result = false; + + // + // Check Signal Type is Enabled or not ... + bool isTypePassed = mAllowLong || mAllowShort; + + // + // Check Signalling Time ... + MqlDateTime cTime; + bool isTimeRecieved = TimeCurrent(cTime); + + // + int endHour = EndSignallingHoure(); + int startHour = StartSignallingHoure(); + + // + bool isStartHourPassed = + startHour <= -1 + ? true + : cTime.hour >= startHour; + bool isEndHourPassed = + endHour <= -1 + ? true + : cTime.hour < endHour; + bool isTimePassed = isTimeRecieved && isStartHourPassed && isEndHourPassed; + + // + result = isTypePassed && isTimePassed; + + // + return result; + } + + // + bool CanCloseOnTime() + { + // + bool result = false; + + // + result = mCloseOnSpecificTime >= 0 && mCloseOnSpecificTime <= 23; + if (!result) + { + return result; + } + + // + MqlDateTime timeStruct; + result = TimeCurrent(timeStruct); + if (!result) + { + return result; + } + + // + result = timeStruct.hour == mCloseOnSpecificTime; + + // + return result; + } + + // + // Custom Signal Execution ... + void HandleSignals(XSignal &signals[]) + { + // + int signalsCount = ArraySize(signals); + if (!IsValidSize(signals)) + { + return; + } + + // + bool isMarginPassed = IsMarginPassed(); + if (!isMarginPassed) + { + // + string message = "No Margin For Execute Signals ..."; + + // + Alert(message); + + // + EQMHandleForceState(signals); + + // + return; + } + + // + bool isNumberOfPositionsPassed = IsNumberOfPositionsPassed(); + if (!isNumberOfPositionsPassed) + { + // + string message = "Max Allowed Signals Reached ..."; + + // + Alert(message); + + // + return; + } + + // + bool executeOnBreakouts = ExecuteSignalsOnBreakout(); + if (executeOnBreakouts) + { + // + XSignal bSignals[]; + int bSignalsCount = mTradeHandler.GetBreakoutsSignals(bSignals); + if (IsValidSize(bSignalsCount)) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT states[]; + int executedSignalsCount = ExecuteSignals( + signals, + states, + false // + ); + } + } + else + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT states[]; + int executedSignalsCount = ExecuteSignals( + signals, + states, + false // + ); + } + } + + // + // Check Delay Between Two Signals ... + bool IsSignalDelayPassed( + XSignal &signal // + ) + { + // + bool result = false; + + // + // Check Signal Validation ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Check Delay Signals Allowed ... + int delay = DelayBetweenTwoSignal(); + result = delay <= 0; + if (result) + { + return result; + } + + // + // Retrieve Positions ... + // Based On Provider and Symbol and TimeFrame ... + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions, + signal.symbol, + NULL, // signal.provider, + NULL, // signal.period, + ToPositionType(signal.type), + true // Filter By Magic ... + ); + result = !IsValidSize(positionsCount); + if (result) + { + return result; + } + + // + XPosition youngest; + int youngestAge = GetYoungest( + youngest, + positions // + ); + result = youngestAge >= delay; + + // + return result; + } + + // + bool IsMarginPassed() + { + // + double freeMargin = mTrader.mAccount.GetFreeMargin(); + double minFreeMargingForHandleForce = MinFreeMargingForOpenTrades(); + + // + bool result = minFreeMargingForHandleForce <= 0 + ? true + : freeMargin >= minFreeMargingForHandleForce; + + // + return result; + } + + // + bool IsNumberOfPositionsPassed() + { + // + bool result = false; + + // + // int maxAllowed = MaxPositionsForce(); + // result = maxAllowed <= 0; + // if (result) + // { + // return result; + // } + + // // + // XPosition positions[]; + // int positionsCount = mTrader.GetPositions(positions); + // result = !IsValidSize(positionsCount); + // if (result) + // { + // return result; + // } + + // // + // result = positionsCount < maxAllowed; + + // + result = true; + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + + // + // Signals ... + bool mAllowLong; // Allow Long + bool mAllowShort; // Allow Short + int mReuiredSignalVerifications; // Required Verifications for Validate Signals + bool mExecuteSignalsOnBreakout; // Execute Signals On Breakouts + bool mGetVerificationFromOtherTimeFrames; // Get Verifications from Other Time Frames + + // + // Risk Management ... + double mVolume; // Volume + double mTPPoint; // TP Point + double mSLPoint; // SL Point + int mMaxAllowedTrades; // Max Alloed Positions + bool mUseMaxAllowedPerDirection; // Use Max Allowed Positions Per Direction + bool mIgnoreTP; // Ignore Calculated TP + bool mIgnoreSL; // Ignore Calculated SL + + // + // Signalling ... + bool mCloseOnOpposit; // Close all Positions on Opposit + int mEndSignallingHoure; // End Signalling at Specific Time + int mCloseOnSpecificTime; // Close All Trades in Specific Time + int mStartSignallingHoure; // Start Signalling at Specific Time + + // + // Force State: + // we can do many things in force state: + // - Prepare Force Hedging; + // - Receive Signals with minimal Verifications; + // - Increase Volume Size of in Profit Positions; + // - etc ... + // bool mForceState; // Determine in Force State or not + int mDelayBetweenTwoSignal; // Delay between two same signal + int mMaxPositionsForce; // Max Number of Positions For Guard Handling + double mMaxDrawdownForce; // Force Handling State on Drawdown for Guard + bool mAllowSymbolHedgeOnForce; // Allow Symbol Hedging on Force States + double mMinFreeMargingForOpenTrades; // Min Free Margin for Open Trades + + // + XTradeHandler *mTradeHandler; // Handle all Event which related to Signals and Positions + + // + // Apply Default Configurations ... + void DefaultConfigs() + { + // + // Signals ... + AllowLong(false); + AllowShort(false); + ReuiredSignalVerifications(0); + GetVerificationFromOtherTimeFrames(false); + + // + // Risk Management ... + TPPoint(0); + SLPoint(0); + Volume(0.01); + IgnoreTP(false); + IgnoreSL(false); + MaxAllowedTrades(0); + + // + // Signalling ... + CloseOnOpposit(false); + EndSignallingHoure(-1); + CloseOnSpecificTime(-1); + StartSignallingHoure(-1); + + // + // Trailling ... + AllowTrailStop(false); + NextTrailPoint(0); + FirstTrailPoint(0); + NextTrailDistance(0); + FirstTrailDistance(0); + + // + // Supporting ... + AllowSupport(false); + MaxNumberOfSupports(0); + SupportVolumeMultiplier(0.01); + MaxAllowedSupportVolume(0.08); + + // + // Grid ... + AllowGrid(false); + GridDistance(0); + MaxNumberOfGrids(0); + GridVolumeMultiplier(0.01); + MaxAllowedGridVolume(0.08); + + // + // Recovery ... + AllowRecovery(false); + MaxNumberOfRecoveries(0); + RecoveryDistance(0); + RecoveryVolumeMultiplier(0.01); + MaxAllowedRecoveryVolume(0.08); + + // + SaveResults(false); + SaveSignalsOnly(true); + } + + // + XSCX121SetupCycles *mSetups[]; // Number of Setups + + // + // Tools ... + int CountSetups() + { + return ArraySize(mSetups); + } + + // + int FindSetupIndex( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + int result = -1; + + // + int count = CountSetups(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSCX121SetupCycles *iSetup = mSetups[i]; + + // + X121SetupInputs iInputs = iSetup.GetInputs(); + + // + if (iInputs.symbol == symbol && iInputs.period == period) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + int FindSetupIndex( + string symbol // + ) + { + // + int result = -1; + + // + int count = CountSetups(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSCX121SetupCycles *iSetup = mSetups[i]; + + // + X121SetupInputs iInputs = iSetup.GetInputs(); + + // + if (iInputs.symbol == symbol) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + // EQM Functions ... + + // + // Force Close All Positions Due EQM Hedge ... + bool DoEQMForceClose() + { + // + bool result = false; + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + result = IsValidSize(positionsCount); + if (!result) + { + return result; + } + + // + double profit = SpecifiedCalculatePositionsProfit( + positions // + ); + + // + string comment = XEQMSupportToken + " Hedge ..."; + int closed = Close( + positions, + comment // + ); + + // + result = IsValidSize(closed); + if (result) + { + // + mForce = false; + mTradeHandler.Sync(); + } + + // + // Handle Sleeping ... + int restingTime = RestingAfterHedge(); + if (result && IsValidSize(restingTime)) + { + Sleeping(restingTime); + } + + // + return result; + } + + // + // Do Gridding Mechanism ... + void DoEQMProtect() + { + // + XSignal supports[]; + int supportsCount = mTradeHandler.DoProtect( + supports, + mSetups // + ); + + // + if (IsValidSize(supportsCount)) + { + EQMExecuteSignals(supports); + } + } + + // + // Handle Close Trades on Specific Time ... + void DoEQMCloseOnSpecificTime() + { + // + bool canClose = CanCloseOnTime(); + if (!canClose) + { + return; + } + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + string comment = XEQMSupportToken + " Close On Specific Time ..."; + + // + int closed = Close( + positions, + comment // + ); + if (IsValidSize(closed)) + { + // + string message = XEQMSupportToken + " Closed " + ToString(closed) + " Positions on Specified Time ..."; + + // + Alert(message); + } + } + + // + // Handle Force State Management ... + bool mForce; + void EQMHandleForceState(XSignal &forceSignals[]) + { + // + // Validate Force Marigin ... + return; + double drawdown = GetDrawdownPercent(); + double marigin = mTrader.mAccount.GetMargin(); + double minFreeMarigin = MinFreeMargingForOpenTrades(); + double forceMargin = minFreeMarigin * 2; // TODO: Make It Configurable + bool isMarginForce = marigin >= forceMargin; + bool isMarginHotForce = marigin >= forceMargin * 3; + bool isHotDrawdown = drawdown >= 10; + + // + // Retrieving Positions ... + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + // + mForce = false; + return; + } + bool isPositionsCountHotForce = positionsCount >= 10; + + // + XPosition oldest; + int oldestAge = GetOldest( + oldest, + positions // + ); + + // + // Check Force State ... + bool isForce = isMarginForce && oldestAge >= 288; + if (!isForce) + { + // + if (mForce) + { + mForce = false; + } + return; + } + else + { + mForce = true; + } + + // + // Prevent Moving Forward From Non Force State ... + if (!mForce) + { + return; + } + return; + + // + double minProfitPerTrade = MinProfitPerTrade(); + double minProfitPerVolumeFactor = MinProfitPerVolumeFactor(); + + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + + // + XSymbolPositions symbolPositions[]; + int symbolPositionsCount = ExtractSymbolPositions( + positions, + symbolPositions, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (!IsValidSize(symbolPositionsCount)) + { + return; + } + + // + XSignal signals[]; + int forceSignalsCount = ArraySize(forceSignals); + if (IsValidSize(forceSignalsCount)) + { + // + // Check if Symbol Contains or Not ... + for (int i = 0; i < forceSignalsCount; i++) + { + // + XSignal iForceSignal = forceSignals[i]; + + // + int symbolIDX = -1; + bool isSymbolContains = IsContainsSymbol( + iForceSignal.symbol, + symbolIDX, + symbolPositions // + ); + if (!isSymbolContains) + { + // + AddRef( + iForceSignal, + signals // + ); + + // + continue; + } + else + { + // + ENUM_POSITION_TYPE iType = iForceSignal.type; + bool isLong = IsLong(iType); + + // + XSymbolPositions iSymbolPositions = symbolPositions[symbolIDX]; + if (isLong) + { + // + if (iSymbolPositions.longsProfit > 0) + { + // + if (!isMarginHotForce && !isPositionsCountHotForce) + { + // + AddRef( + iForceSignal, + signals // + ); + } + else + { + } + } + else + { + // + // In Drawdown ... + if (isMarginHotForce && !isPositionsCountHotForce) + { + } + else + { + // + bool hasSupport = iSymbolPositions.HasLongSupport(); + if (hasSupport) + { + continue; + } + + // + mTradeHandler.AllowToGrid(iForceSignal); + AddRef( + iForceSignal, + signals // + ); + } + } + } + else + { + // + if (iSymbolPositions.shortsProfit > 0) + { + // + if (!isMarginHotForce && !isPositionsCountHotForce) + { + // + AddRef( + iForceSignal, + signals // + ); + } + else + { + } + } + else + { + // + // In Drawdown ... + if (!isMarginHotForce && !isPositionsCountHotForce) + { + } + else + { + // + bool hasSupport = iSymbolPositions.HasShortSupport(); + if (hasSupport) + { + continue; + } + + // + mTradeHandler.AllowToGrid(iForceSignal); + AddRef( + iForceSignal, + signals // + ); + } + } + } + } + } + } + + // + int signalsCount = ArraySize(signals); + if (IsValidSize(signalsCount)) + { + EQMExecuteSignals(signals); + } + else + { + // + // Handle CLosing ... + if (!isMarginHotForce && !isHotDrawdown) + { + return; + } + + // + for (int i = 0; i < symbolPositionsCount; i++) + { + // + XSymbolPositions iSymbolPositions = symbolPositions[i]; + + // + if (!iSymbolPositions.HasChild()) + { + continue; + } + + // + if (iSymbolPositions.profit > 0) + { + continue; + } + + // + // XPosition iOldest; + // int oldestAge = GetOldest( + // iOldest, + // iSymbolPositions.positions // + // ); + // if (oldestAge <= 140) + // { + // continue; + // } + + // + int maxInDPIDX = FindMaxDrawdownIndex( + iSymbolPositions.positions // + ); + if (!IsValidIndex(maxInDPIDX)) + { + continue; + } + + // + XPosition maxInDP = iSymbolPositions.positions[maxInDPIDX]; + int age = GetAge( + maxInDP, + maxInDP.period // + ); + if (age <= 288) + { + continue; + } + + // + string comment = XEQMSupportToken + " Close due Max In D ..."; + bool isClosed = mTrader.Close( + maxInDP.ticket, + comment // + ); + if (isClosed) + { + // + string message = XEQMSupportToken + " Close (" + ToString(maxInDP.ticket) + ") due Max In D ..."; + + // + Alert(message); + } + } + } + + // + } + + // + // Handle any Invalid Signals ... + void EQMHandleInvalidSignal( + XSignal &signal, // Invalid Signal + int pushers, // Pushers + bool isValid, // IsValid Signal ... + X121SetupConditions &conditions[] // All Time Frames Conditions + ) + { + // + if (!mForce) + { + return; + } + + // + XSignal signals[]; + + // + // || pushers >= 3 + if (isValid) + { + // + bool canSupport = + // + mForce && + EnableSupport() && + SupportOnlyForces() + // + ; + bool canGrid = + // + mForce && + EnableGrid() && + GridOnlyForces() + // + ; + bool canRecover = + // + mForce && + EnableRecovery() && + RecoverOnlyForces() + // + ; + + // + AddRef( + signal, + signals // + ); + + // + // Add new Signal Info ... + mTradeHandler.Add( + signal, + pushers, + canGrid, + canRecover, + canSupport, + conditions[0], + conditions[1], + conditions[2], + conditions[3], + conditions[4] // + ); + } + + // + if (ArraySize(signals) > 0) + { + // + EQMExecuteSignals(signals); + // EQMHandleForceState(signals); + } + } + + // + void EQMExecuteSignals( + XSignal &signals[] // + ) + { + // + int signalsCount = ArraySize(signals); + if (!IsValidSize(signals)) + { + return; + } + + // + // + // Execute Supports ... + ENUM_X_SIGNAL_EXECUTION_RESULT states[]; + int executed = ExecuteSignals( + signals, + states, + false // Ignore Policies ... + ); + if (executed != signalsCount) + { + // + // TODO: Dow What We Want ... + // Print("Error On Executing Support Signal ..."); + } + + // + // Remove Supported Signals TP and SL and leave them for Handling using HEDGE Mechanism ... + if (IsValidSize(executed)) + { + // + for (int i = 0; i < signalsCount; i++) + { + // + ENUM_X_SIGNAL_EXECUTION_RESULT iState = states[i]; + if (iState != X_SIGNAL_EXECUTION_SUCCEED) + { + continue; + } + + // + XSignal iSignal = signals[i]; + if (!iSignal.IsValid() || !iSignal.IsExecuted()) + { + continue; + } + + // + ulong iParentTicket = ExtractParentTicket(iSignal.comment); + if (iParentTicket <= 0) + { + continue; + } + + // + XPosition iParent; + bool hasParent = mTrader.GetPosition( + iParentTicket, + iParent // + ); + if (!hasParent) + { + continue; + } + + // + // Check Parent Has TP or SL ... + if (iParent.tp == 0 && iParent.sl == 0) + { + continue; + } + + // + // Remove TP and SL of Supported Positions ... + string comment = "EQM Remove TPSL ..."; + bool isModified = Modify( + iParentTicket, + 0, + 0, + comment // + ); + if (isModified) + { + // + // TODO: + // do What we want ... + } + } + } + } + + // +}; + +// diff --git a/Experts/x-saherelm.x121.ea.mq5 b/Experts/x-saherelm.x121.ea.mq5 index b3ed0529..7fc9cd39 100644 --- a/Experts/x-saherelm.x121.ea.mq5 +++ b/Experts/x-saherelm.x121.ea.mq5 @@ -94,11 +94,11 @@ input double x121EAMaxAllowedSupportVolume = 0; // Max Allowed Support Signals V // input group "Grid"; -input bool x121EAAllowGrid = false; // Allow Grid Signals -input bool x121EAGridOnlyForces = false; // Grid Only Force Signals +input bool x121EAAllowGrid = true; // Allow Grid Signals +input bool x121EAGridOnlyForces = true; // Grid Only Force Signals input int x121EAMaxNumberOfGrids = 0; // Max Number of Grid Signals -input double x121EAGridDistance = 0; // Grid Distance -input double x121EAGridVolumeMultiplier = 0; // Grid Volume Multiplier +input double x121EAGridDistance = 200; // Grid Distance +input double x121EAGridVolumeMultiplier = 2; // Grid Volume Multiplier input double x121EAMaxAllowedGridVolume = 0; // Max Allowed Grid Signals Volume // diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index 2aff8c59..557b2f7a 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -2929,6 +2929,98 @@ struct XSymbolPositions return ArraySize(positions); } + // + int CountLongs() + { + return ArraySize(longs); + } + + // + int CountShorts() + { + return ArraySize(shorts); + } + + // + bool HasSupport() + { + // + bool result = false; + + // + result = HasChild(); + if (!result) + { + return result; + } + + // + result = HasLongSupport() || HasShortSupport(); + + // + return result; + } + + // + bool HasLongSupport() + { + // + bool result = false; + + // + int count = CountLongs(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = longs[i]; + result = IsSupport(iPosition.comment); + if (result) + { + break; + } + } + + // + return result; + } + + // + bool HasShortSupport() + { + // + bool result = false; + + // + int count = CountShorts(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = shorts[i]; + result = IsSupport(iPosition.comment); + if (result) + { + break; + } + } + + // + return result; + } + // };