diff --git a/Classes/x-saherelm.x121.provider.class.mq5 b/Classes/x-saherelm.x121.provider.class.mq5 index a897ecec..5d7f705c 100644 --- a/Classes/x-saherelm.x121.provider.class.mq5 +++ b/Classes/x-saherelm.x121.provider.class.mq5 @@ -53,6 +53,7 @@ enum ENUM_X121_SIGNAL_PROVIDERS X121, X110, X92, + X128, }; // @@ -1390,7 +1391,7 @@ public: // mNumberOfItems = 15; mNumberOfSRVerified = 71; - mMinRequiredSupportAndResistances = 10; + mMinRequiredSupportAndResistances = 30; } // @@ -1670,6 +1671,11 @@ public: case X92: mIsX92SignalProviderEnable = state; break; + + // + case X128: + mIsX128SignalProviderEnable = state; + break; } } @@ -1907,6 +1913,17 @@ public: : entry + risk; } + // + // TODOO: Remove this ... + sl = hasLong + ? GetMaxVales(true) + : GetMinPeaks(true); + double risk = MathAbs(entry - sl); + double reward = risk * r2r; + tp = hasLong + ? entry + reward + : entry - reward; + // result = mSignal.Prepare( symbol, @@ -1923,17 +1940,103 @@ public: ); // - if (result) + // Generate Support Signal for Specified Provider ... + if (result && provider == ToString(X121NONE)) { // - mWaitsUntilNewBar = true; + double cKijunSen = cMarket.ich.GetKijunSen(0); + double sKijunSen = sMarket.ich.GetKijunSen(0); + double mKijunSen = mMarket.ich.GetKijunSen(0); + double lKijunSen = lMarket.ich.GetKijunSen(0); + double hKijunSen = hMarket.ich.GetKijunSen(0); - // // - // TODO: - // string providerTypeStr = GetSymbol() + ", " + provider + "(" + (hasLong ? "Long" : "Short") + ")"; - // string mConditionsStr = mConditions.GenerateSummary(providerTypeStr, true); - // mConditionsCollector.Add(mConditionsStr); - // Print(mConditionsStr); + // + double kijunSens[] = { + cKijunSen, + sKijunSen, + mKijunSen, + lKijunSen, + hKijunSen // + }; + + // + double lesserKijun = FindLesserThan( + entry, + kijunSens, + true // + ); + + // + double biggerKijun = FindBiggerThan( + entry, + kijunSens, + true // + ); + + // + ENUM_POSITION_TYPE sType = + hasLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + bool isLongS = IsLong(sType); + + // + double sEntry = + isLongS + ? biggerKijun + : lesserKijun; + + // + double peakMin = GetMinPeaks(true); + double peakMax = GetMinPeaks(true); + double valeMin = GetMaxVales(true); + double valeMax = GetMaxVales(true); + + // + double sTP = + isLongS + ? peakMin + : valeMax; + + // + double sSL = + isLongS + ? valeMin + : peakMax; + + // + double sVolume = mSignal.volume * 2; + + // + // Prepare ... + XSignal sSignal; + bool isValid = sSignal.Prepare( + mSignal.symbol, + mSignal.provider, + mSignal.period, + sType, + X_ORDER_MODE_STOP, + sEntry, + sVolume, + X_SIGNAL_USE_NOTHING, + sSL, + sTP // + ); + if (isValid) + { + // + AddRef( + sSignal, + mSignal.supports // + ); + } + } + + // + if (result) + { + mWaitsUntilNewBar = true; } } @@ -1958,6 +2061,24 @@ public: // return result; } + + // + // Generate EQM Support Signals ... + int GenerateEQMSupportSignals(XSignal &supports[]) { + // + int result = 0; + + // + Clean(signals); + + // + // TODO: Implement Support Mechanism ... + // we are in EQUITY STATE ... + // so we have to + + // + return result; + } // // Tools ... @@ -2105,8 +2226,15 @@ public: // Peask and Vales Finder ... // - double GetMinPeaks() + void GetPeaks( + double &peaks[], + bool ignoreCurrent = false // + ) { + // + Clean(peaks); + + // // double cPeak = cMarket.pv.GetPeak(0); double sPeak = sMarket.pv.GetPeak(0); @@ -2115,7 +2243,7 @@ public: double hPeak = hMarket.pv.GetPeak(0); // - double peaks[] = { + double mPeaks[] = { cPeak, sPeak, mPeak, @@ -2123,6 +2251,75 @@ public: hPeak // }; + // + if (ignoreCurrent) + { + // + Remove( + cPeak, + mPeaks // + ); + } + + // + Copy( + mPeaks, + peaks // + ); + } + + // + void GetVales( + double &vales[], + bool ignoreCurrent = false // + ) + { + // + Clean(vales); + + // + double cVale = cMarket.pv.GetVale(0); + double sVale = sMarket.pv.GetVale(0); + double mVale = mMarket.pv.GetVale(0); + double lVale = lMarket.pv.GetVale(0); + double hVale = hMarket.pv.GetVale(0); + + // + double mVales[] = { + cVale, + sVale, + mVale, + lVale, + hVale // + }; + + // + if (ignoreCurrent) + { + // + Remove( + cVale, + mVales // + ); + } + + // + Copy( + mVales, + vales // + ); + } + + // + double GetMinPeaks(bool ignoreCurrent = false) + { + // + double peaks[]; + GetPeaks( + peaks, + ignoreCurrent // + ); + // double minPeak = GetMin(peaks); double maxPeak = GetMax(peaks); @@ -2132,23 +2329,14 @@ public: } // - double GetMaxPeaks() + double GetMaxPeaks(bool ignoreCurrent = false) { // - double cPeak = cMarket.pv.GetPeak(0); - double sPeak = sMarket.pv.GetPeak(0); - double mPeak = mMarket.pv.GetPeak(0); - double lPeak = lMarket.pv.GetPeak(0); - double hPeak = hMarket.pv.GetPeak(0); - - // - double peaks[] = { - cPeak, - sPeak, - mPeak, - lPeak, - hPeak // - }; + double peaks[]; + GetPeaks( + peaks, + ignoreCurrent // + ); // double minPeak = GetMin(peaks); @@ -2159,23 +2347,14 @@ public: } // - double GetMinVales() + double GetMinVales(bool ignoreCurrent = false) { // - double cMVale = cMarket.pv.GetVale(0); - double sMVale = sMarket.pv.GetVale(0); - double mMVale = mMarket.pv.GetVale(0); - double lMVale = lMarket.pv.GetVale(0); - double hMVale = hMarket.pv.GetVale(0); - - // - double vales[] = { - cMVale, - sMVale, - mMVale, - lMVale, - hMVale // - }; + double vales[]; + GetVales( + vales, + ignoreCurrent // + ); // double minVale = GetMin(vales); @@ -2186,23 +2365,14 @@ public: } // - double GetMaxVales() + double GetMaxVales(bool ignoreCurrent = false) { // - double cMVale = cMarket.pv.GetVale(0); - double sMVale = sMarket.pv.GetVale(0); - double mMVale = mMarket.pv.GetVale(0); - double lMVale = lMarket.pv.GetVale(0); - double hMVale = hMarket.pv.GetVale(0); - - // - double vales[] = { - cMVale, - sMVale, - mMVale, - lMVale, - hMVale // - }; + double vales[]; + GetVales( + vales, + ignoreCurrent // + ); // double minVale = GetMin(vales); @@ -2869,6 +3039,7 @@ private: // bool mIsX121XSPSignalProviderEnable; + bool mIsX128SignalProviderEnable; bool mIsX92SignalProviderEnable; bool mIsX786SignalProviderEnable; bool mIsX121SignalProviderEnable; @@ -2922,6 +3093,7 @@ private: bool hasX121Signal = false; bool hasX110Signal = false; bool hasX92Signal = false; + bool hasX128Signal = false; // // XPS ... @@ -3073,6 +3245,31 @@ private: } } + // + // X128 ... + if (mIsX128SignalProviderEnable) + { + // + hasX128Signal = X128HasSpecifiedLongSignal( + mConditions, + providedSL, + providedTP // + ); + + // + if (hasX128Signal) + { + // + if (!IsValid(provider)) + { + provider = ToString(X128); + } + + // + signalPusher++; + } + } + // result = // @@ -3098,6 +3295,10 @@ private: // hasX92Signal // + || + // + hasX128Signal + // ; // @@ -3124,6 +3325,7 @@ private: bool hasX121Signal = false; bool hasX110Signal = false; bool hasX92Signal = false; + bool hasX128Signal = false; // // X121XSP ... @@ -3275,6 +3477,31 @@ private: } } + // + // X128 ... + if (mIsX128SignalProviderEnable) + { + // + hasX128Signal = X128HasSpecifiedShortSignal( + mConditions, + providedSL, + providedTP // + ); + + // + if (hasX128Signal) + { + // + if (!IsValid(provider)) + { + provider = ToString(X128); + } + + // + signalPusher++; + } + } + // result = // @@ -3300,6 +3527,10 @@ private: // hasX92Signal // + || + // + hasX128Signal + // ; // @@ -4149,9 +4380,9 @@ private: // result = // - isCMStrLong - // - || + // isCMStrLong + // // + // || // isSMStrLong // @@ -4318,10 +4549,10 @@ private: // result = - // - isCMCLong - // - || + // // + // isCMCLong + // // + // || // isSMCLong // @@ -4423,10 +4654,10 @@ private: // result = - // - isCCHELong - // - || + // // + // isCCHELong + // // + // || // isSCHELong // @@ -4469,46 +4700,19 @@ private: bool result = false; // - double bullishScore = mBullishScore[0]; - double bullishMin100 = GetBullishScoreMin(0, 100); - double bullishMax100 = GetBullishScoreMax(0, 100); - double bullish9AVG = GetBullishScoreAverage(0, 9); - double bullish17AVG = GetBullishScoreAverage(0, 17); - double bullish26AVG = GetBullishScoreAverage(0, 26); + return result; + } + // + // Use XICH ... + bool X128HasSpecifiedLongSignal( + X121MarketConditions &mConditions, // + double &sl, // Provided SL ... + double &tp // Provided TP ... + ) + { // - double bearishScore = mBearishScore[0]; - - // - bool isScorePassed = IsScorePassedForLong(); - - // - bool isBullishOverAVGs = - // - ArraySize(mBullishScore) > 100 && - bullishScore > mBullishScore[1] && - bullishScore > bearishScore && - bullishScore > bullish9AVG && - bullishScore > bullish17AVG && - bullishScore > bullish26AVG - // - ; - - // - result = - // - isBullishOverAVGs - // - ; - - // - result = result && isScorePassed; - - // - if (result) - { - sl = GetMinVales(); - } + bool result = false; // return result; @@ -4613,10 +4817,10 @@ private: // result = - // - isCMStrShort - // - || + // // + // isCMStrShort + // // + // || // isSMStrShort // @@ -4783,10 +4987,10 @@ private: // result = - // - isCMCShort - // - || + // // + // isCMCShort + // // + // || // isSMCShort // @@ -4888,10 +5092,10 @@ private: // result = - // - isCCHEShort - // - || + // // + // isCCHEShort + // // + // || // isSCHEShort // @@ -4934,46 +5138,19 @@ private: bool result = false; // - double bearishScore = mBearishScore[0]; - double bearishMin100 = GetBearishScoreMin(0, 100); - double bearishMax100 = GetBearishScoreMax(0, 100); - double bearish9AVG = GetBearishScoreAverage(0, 9); - double bearish17AVG = GetBearishScoreAverage(0, 17); - double bearish26AVG = GetBearishScoreAverage(0, 26); + return result; + } + // + // Use XICH ... + bool X128HasSpecifiedShortSignal( + X121MarketConditions &mConditions, // + double &sl, // Provided SL ... + double &tp // Provided TP ... + ) + { // - double bullishScore = mBullishScore[0]; - - // - bool isBearishOverAVGs = - // - ArraySize(mBearishScore) > 100 && - bearishScore > mBearishScore[1] && - bearishScore > bullishScore && - bearishScore > bearish9AVG && - bearishScore > bearish17AVG && - bearishScore > bearish26AVG - // - ; - - // - bool isScorePassed = IsScorePassedForShort(); - - // - result = - // - isBearishOverAVGs - // - ; - - // - result = result && isScorePassed; - - // - if (result) - { - sl = GetMaxPeaks(); - } + bool result = false; // return result; @@ -5212,6 +5389,7 @@ void GetAllX121SignalProviders(ENUM_X121_SIGNAL_PROVIDERS &result[]) Add(X121, result); Add(X110, result); Add(X92, result); + Add(X128, result); } // @@ -5261,6 +5439,10 @@ ENUM_X121_SIGNAL_PROVIDERS ToX121SignalProvider(string content) { result = X92; } + else if (content == ToString(X128)) + { + result = X128; + } // return result; diff --git a/Classes/x-saherelm.x121.xea.class.mq5 b/Classes/x-saherelm.x121.xea.class.mq5 index 5acefcb4..af29320d 100644 --- a/Classes/x-saherelm.x121.xea.class.mq5 +++ b/Classes/x-saherelm.x121.xea.class.mq5 @@ -283,7 +283,7 @@ public: // // Handl Management Actions ... // if returns true, it is going to prevent for processing forward ... - bool HandleStateManagement() override + bool HandleStateManagement(XSignal &signals[]) override { // bool result = false; @@ -297,7 +297,7 @@ public: } // - HandleEQMState(); + HandleEQMState(signals); // HandleHedging(positions); @@ -344,9 +344,7 @@ public: string comment = "EQM Hedge ..."; int closed = mTrader.Close( positions, - comment - // - ); + comment); if (closed > 0) { // @@ -358,14 +356,14 @@ public: // for (int i = 0; i < positionsCount; i++) { - RemoveSLTrail(positions[i].ticket); + RemoveTrail(positions[i].ticket); } } } } // - void HandleEQMState() + void HandleEQMState(XSignal &signals[]) { // bool equityReached = !mTrader.CheckEquityForTrade(); @@ -378,8 +376,75 @@ public: } // - Print("EQM Enabled: " + (equityReached ? "Max Equity Reached ..." : maxAllowedReached ? "Max Allowed Positions Reached ..." - : "")); + string eqmMessage = "EQM Enabled: " + "\n"; + if (equityReached) + { + eqmMessage += "- Max Equity Reached ..." + "\n"; + } + if (maxAllowedReached) + { + eqmMessage += "- Max Allowed Positions Reached ..."; + } + mAlert.Alert(eqmMessage); + + // + int descriptorsCount = CountDescriptors(); + if (descriptorsCount <= 0) + { + return; + } + + // + XSignal supportSignals[]; + for (int i = 0; i < descriptorsCount; i++) + { + // + X121ProviderDescriptor iDescriptor = mDescriptors[i]; + + // + XSignal iSupportSignals[]; + int iSupportSignalsCount = iDescriptor + .provider + .GenerateEQMSupportSignals( + iSupportSignals // + ); + if (iSupportSignalsCount <= 0) + { + continue; + } + + // + Copy( + iSupportSignals, + supportSignals, + false // + ); + } + + // + int supportSignalsCount = ArraySize(supportSignals); + if (supportSignalsCount <= 0) + { + return; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT states[]; + int executedSupports = mTrader.ExecuteSignals( + supportSignals, + states, + ORDER_TIME_GTC, + NULL, + false // Ignore Policies ... + ); + if (executedSupports > 0) + { + // + string message = "EQM Execute (" + ToString(executedSupports) + ") Support Signals ..."; + + // + mAlert.Alert(message); + } } // @@ -389,8 +454,8 @@ public: // TODO: // Make them Configurable ... int levelsOnClose = 6; - int requiredAgeForSLTrail = 3; - int requiredDistanceForSLTrail = 10; + int requiredAgeForSLTrail = 0; + int requiredDistanceForSLTrail = 30; // int positionsCount = ArraySize(positions); @@ -409,10 +474,7 @@ public: // bool canManageState = // - iPosition.provider == ToString(X786) || - iPosition.provider == ToString(X121) || - iPosition.provider == ToString(X110) || - iPosition.provider == ToString(X92) + true // ; @@ -475,7 +537,8 @@ public: iPosition.type, iPosition.profit, iPosition.sl, - sl); + sl // + ); if (!isInit) { continue; @@ -510,43 +573,190 @@ public: // double priceDistanceInPoint = PriceToPoint((iPosition.profit - trail.profit) / iPosition.volume, iPosition.symbol); double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); - if (priceDistance < requiredDistanceForSLTrail) + if (priceDistance < (requiredDistanceForSLTrail / 2)) { - // - // int positionAge = iPosition.GetAge(iPosition.period); - if (trail.level >= levelsOnClose) - { - // - string comment = "EQM Close In Profit ..."; - bool isClosed = mTrader.Close( - iPosition.ticket, - comment // - ); - if (isClosed) - { - // - RemoveSLTrail(iPosition.ticket); + // // + // // int positionAge = iPosition.GetAge(iPosition.period); + // if (trail.level >= levelsOnClose) + // { + // // + // string comment = "EQM Close In Profit ..."; + // bool isClosed = mTrader.ClosePositionPack( + // iPosition.ticket, + // iPosition.symbol, + // iPosition.period, + // comment, + // true, + // GetMinProfitPerTrade(), + // GetMinProfitPerVolumeFactor() // + // ); + // if (isClosed) + // { + // // + // RemoveTrail(iPosition.ticket); - // - string message = "EQM Close (" + ToString(iPosition.ticket) + ") In Profit ..."; - mAlert.Alert(message); - } - } + // // + // string message = "EQM Close (" + ToString(iPosition.ticket) + ") In Profit ..."; + // mAlert.Alert(message); + // } + // } continue; } + // + bool isLong = IsLong(iPosition.type); + // double slDiff = PointToPrice(priceDistance, iPosition.symbol); // double selectedValue = // - trail.level == 2 + trail.level == 1 || (isLong + ? iPosition.sl < iPosition.entry + : iPosition.sl > iPosition.entry) ? iPosition.entry : iPosition.sl // ; + // + double sl = + isLong + ? selectedValue + slDiff + : selectedValue - slDiff; + + // + // Update Trail Values ... + bool isUpdated = trail.Update( + sl, + iPosition.profit // + ); + if (!isUpdated) + { + continue; + } + } + + // + if (trail.IsValid()) + { + // + string comment = trail.GenerateTag(); + bool isModified = mTrader.Modify( + trail.ticket, + trail.after, + iPosition.tp, + comment // + ); + if (isModified) + { + // + RemoveTrail(trail.ticket); + + // + AddSLTrail(trail); + + // + string message = "Position (" + ToString(trail.ticket) + ") Trailed SL on Level: " + ToString(trail.level); + mAlert.Alert(message); + } + } + } + else if (iPosition.profit < 0) + { + // + XTrail trail; + bool isTrailedBefore = GetSLTrail( + iPosition.ticket, + trail // + ); + + // + if (!isTrailedBefore) + { + // + // Add First Time ... + + // + // Check Position Age ... + int iPositionAge = iPosition.GetAge(iPosition.period); + if (iPositionAge < requiredAgeForSLTrail) + { + continue; + } + + // + // Check Position Profit Distance ... + double priceDistanceInPoint = PriceToPoint(MathAbs(iPosition.profit) / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + if (priceDistance < requiredDistanceForSLTrail) + { + continue; + } + + // + double slDiff = PointToPrice(priceDistance, iPosition.symbol); + + // + double sl = + IsLong(iPosition.type) + ? iPosition.sl + slDiff + : iPosition.sl - slDiff; + + // + bool isInit = trail.Init( + iPosition.ticket, + iPosition.type, + iPosition.profit, + iPosition.sl, + sl // + ); + if (!isInit) + { + continue; + } + } + else + { + // + // Update Exists ... + + // + // Check Profit ... + bool isProfitPassed = iPosition.profit > trail.profit; + if (!isProfitPassed) + { + continue; + } + + // + // Check Age Distance from Last ... + int age = iBarShift( + iPosition.symbol, + iPosition.period, + trail.time, + false // + ); + if (age < requiredAgeForSLTrail) + { + continue; + } + + // + double priceDistanceInPoint = PriceToPoint((MathAbs(iPosition.profit) - MathAbs(trail.profit)) / iPosition.volume, iPosition.symbol); + double priceDistance = PointToPrice(priceDistanceInPoint, iPosition.symbol); + + // + double slDiff = PointToPrice(priceDistance, iPosition.symbol); + + // + double selectedValue = + // + iPosition.sl + // + ; + // double sl = IsLong(iPosition.type) @@ -579,7 +789,7 @@ public: if (isModified) { // - RemoveSLTrail(trail.ticket); + RemoveTrail(trail.ticket); // AddSLTrail(trail); @@ -622,6 +832,8 @@ public: // Cleaning Source ... Clean(signals); + // + // // Loop through Signals for Management ... for (int i = 0; i < tmpsCount; i++) @@ -652,10 +864,15 @@ public: NULL, // All Periods ... iSignal.type // ); - if (positionsCount < 2) + if (positionsCount <= 0) { // // First Signal in a While of Specific Provider ... + + // + iSignal.volume *= 2; + + // AddRef( iSignal, signals // @@ -664,112 +881,20 @@ public: // continue; } - // else - // { - // // - // // not First Signal ... + else if (positionsCount < 2) + { + // + // First Signal in a While of Specific Provider ... - // // - // // Calculate Provider Specified Open Positions Profit ... - // double profits = CalculatePositionsProfit(positions); - // if (profits > 0) - // { + // + AddRef( + iSignal, + signals // + ); - // // - // AddRef( - // iSignal, - // signals // - // ); - - // // // - // // // Find Max In Profit of Same Position ... - // // Clean(positions); - // // positionsCount = mTrader.GetInProfitPositions( - // // positions, - // // iSignal.symbol, - // // iSignal.provider, - // // NULL, // All Periods ... - // // iSignal.type, - // // X_POSITION_SELECT_MAX // Max In Profit ... - // // ); - // // if (positionsCount <= 0) - // // { - // // continue; - // // } - - // // // - // // string comment = "EQM Close Max Profit ..."; - // // bool isClosed = mTrader.Close( - // // positions[0].ticket, - // // comment // - // // ); - // // if (isClosed) - // // { - // // // - // // RemoveTrail(positions[0].ticket); - - // // // - // // string message = "EQM Close Max In Profit (" + ToString(positions[0].ticket) + ") for new Signal ..."; - - // // // - // // mAlert.Alert(message); - - // // // - // // AddRef( - // // iSignal, - // // signals // - // // ); - - // // // - // // continue; - // // } - // } - // else - // { - // // // - // // // Find Max In Profit of Same Position ... - // // Clean(positions); - // // positionsCount = mTrader.GetInProfitPositions( - // // positions, - // // iSignal.symbol, - // // iSignal.provider, - // // NULL, // All Periods ... - // // iSignal.type, - // // X_POSITION_SELECT_MAX // Max In Profit ... - // // ); - // // if (positionsCount <= 0) - // // { - // // continue; - // // } - - // // // - // // string comment = "EQM Close Max Profit ..."; - // // bool isClosed = mTrader.Close( - // // positions[0].ticket, - // // comment // - // // ); - // // if (isClosed) - // // { - // // // - // // RemoveTrail(positions[0].ticket); - - // // // - // // string message = "EQM Close Max In Profit (" + ToString(positions[0].ticket) + ") for new Signal ..."; - - // // // - // // mAlert.Alert(message); - - // // // - // // AddRef( - // // iSignal, - // // signals // - // // ); - - // // // - // // continue; - // // } - // } - // } + // + continue; + } } // diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index cc18b84e..dae37156 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -582,10 +582,13 @@ public: DoGuards(guards); } + // + XSignal signals[]; + // // Second Check for Position Management or Equity Management // Actions like Supports or etc ... - bool isIgnored = HandleStateManagement(); + bool isIgnored = HandleStateManagement(signals); if (isIgnored) { return; @@ -594,7 +597,6 @@ public: // // Second Check For Signals ... // then Execute Signals if Provided ... - XSignal signals[]; int signalsCount = RequestForSignal(signals); if (signalsCount <= 0) { @@ -740,7 +742,7 @@ public: // // Handle Position(s)/ Order(s) or EQM Supporting Action ... // if returns false, prevent for process Tick ... - virtual bool HandleStateManagement() + virtual bool HandleStateManagement(XSignal &signals[]) { return false; } @@ -929,38 +931,11 @@ protected: ) { // - double result = 0; - - // - int positionsCount = ArraySize(positions); - if (positionsCount <= 0) - { - return result; - } - - // - bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; - if (!isHedgingEnable) - { - return result; - } - - // - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) - { - // - result += - ((iPosition.volume / mMinProfitPerVolumeFactor) * - mMinProfitPerTrade) + - (-1 * iPosition.swap); - } - } + double result = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); // return result; @@ -973,24 +948,7 @@ protected: ) { // - double result = 0; - - // - int positionsCount = ArraySize(positions); - if (positionsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - result += iPosition.profit; - } + double result = SpecifiedCalculatePositionsProfit(positions); // return result; diff --git a/Classes/x-saherelm.xtrade.class.mq5 b/Classes/x-saherelm.xtrade.class.mq5 index 3f409389..ddf872bd 100644 --- a/Classes/x-saherelm.xtrade.class.mq5 +++ b/Classes/x-saherelm.xtrade.class.mq5 @@ -1038,19 +1038,19 @@ public: // NOTE: Call this Before Checking IsNewBar ... void Manage() { - // - // All required Position Managements Actions implemented here ... - datetime tmc = TimeCurrent(); - bool canManage = !IsValid(mLastManageOn) - ? true - : mLastManageOn + mManageInterval >= tmc; - if (!canManage) - { - return; - } + // // + // // All required Position Managements Actions implemented here ... + // datetime tmc = TimeCurrent(); + // bool canManage = !IsValid(mLastManageOn) + // ? true + // : mLastManageOn + mManageInterval >= tmc; + // if (!canManage) + // { + // return; + // } - // - mLastManageOn = tmc; + // // + // mLastManageOn = tmc; // // - [] Partial Close; @@ -2771,6 +2771,337 @@ public: return mResult; } + // + // XPosition Pack ... + + // + // Extract specific Positions Pack ... + // in this senario there is no need to Position exists itself ... + bool GetPositionPack( + ulong ticket, // Specified Positions Ticket + string symbol, // Specified Position Symbol + ENUM_TIMEFRAMES period, // Specified Position Period + XPositionPack &pack // Hold Result + ) + { + // + bool result = false; + + // + pack.Clean(); + + // + XPosition position; + bool hasPosition = GetPosition( + ticket, + position + // + ); + if (hasPosition) + { + pack.position = position; + } + + // + XOrder supportOrders[]; + XPosition supportPositions[]; + + // + XOrder orders[]; + GetOrders( + orders, + symbol, // Specified Symbol + NULL, // All Providers + period, // Specified Period + NULL, // All Types + ORDER_STATE_PLACED, // Just UnTriggered Orders + true // Filter by Magic + ); + int ordersCount = ArraySize(orders); + + // + // Select Orders ... + if (ordersCount > 0) + { + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + // Retrieve Order Supported Ticket ... + ulong parentTicket = ExtractSupportedTicket(iOrder.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iOrder, + supportOrders + // + ); + } + } + } + + // + int supportOrdersCount = ArraySize(supportOrders); + if (supportOrdersCount > 0) + { + // + pack.supportOrdersCount = supportOrdersCount; + + // + Copy( + supportOrders, + pack.supportOrders); + } + + // + XPosition positions[]; + GetPositions( + positions, + symbol, // Specified Symbol ... + NULL, // All Providers ... + period // Specified Period ... + ); + int positionsCount = ArraySize(positions); + + // + // Select Positions ... + if (positionsCount > 0) + { + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + ulong parentTicket = ExtractSupportedTicket(iPosition.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iPosition, + supportPositions + // + ); + } + } + } + + // + int supportPositionsCount = ArraySize(supportPositions); + if (supportPositionsCount > 0) + { + // + pack.supportPositionsCount = supportPositionsCount; + + // + Copy( + supportPositions, + pack.supportPositions); + } + + // + result = pack.IsValid(); + + // + return result; + } + + // + // Close Position Pack ... + bool ClosePositionPack( + XPositionPack &pack, // Specified Position Pack + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + bool result = false; + + // + ulong ticket = pack.ticket; + + // + XPosition positions[]; + + // + XPosition pPosition; + result = GetPosition( + ticket, + pPosition // + ); + if (result) + { + // + AddRef( + pPosition, + positions // + ); + } + + // + if (pack.supportPositionsCount > 0) + { + // + for (int i = 0; i < pack.supportPositionsCount; i++) + { + // + XPosition iPosition = pack.supportPositions[i]; + + // + AddRef( + iPosition, + positions // + ); + } + } + + // + // Force Close ... + if (!inProfit) + { + // + int closed = Close( + positions, + comment // + ); + + // + int cancelled = 0; + if (pack.supportOrdersCount > 0) + { + cancelled = CancelOrders(pack.supportOrders); + } + + // + result = (closed + cancelled) == (pack.supportPositionsCount + pack.supportOrdersCount + 1); + } + else + { + // + bool canHedge = SpecifiedIsPositionsReadyForHedge( + positions, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (canHedge) + { + // + int closed = Close( + positions, + comment // + ); + + // + int cancelled = 0; + if (pack.supportOrdersCount > 0) + { + cancelled = CancelOrders(pack.supportOrders); + } + + // + result = (closed + cancelled) == (pack.supportPositionsCount + pack.supportOrdersCount + 1); + } + else + { + result = false; + } + } + + // + return result; + } + bool ClosePositionPack( + ulong ticket, // Specified Position Pack + string symbol, // Specified Position Symbol + ENUM_TIMEFRAMES period, // Specified Position Period + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + bool result = false; + + // + XPositionPack pack; + result = GetPositionPack( + ticket, + symbol, + period, + pack // + ); + if (!result) + { + return result; + } + + // + result = ClosePositionPack( + pack, + comment, + inProfit, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + + // + return result; + } + + // + // Close Positions Pack ... + int ClosePositionsPack( + XPosition &positions[], // Positions ... + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = ClosePositionPack( + iPosition.ticket, + iPosition.symbol, + iPosition.period, + comment, + inProfit, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + // // Protected ... protected: @@ -2974,146 +3305,6 @@ protected: return result; } - // - // XPosition Pack ... - - // - // Extract specific Positions Pack ... - // in this senario there is no need to Position exists itself ... - bool GetPositionPack( - ulong ticket, // Specified Positions Ticket - string symbol, // Specified Position Symbol - ENUM_TIMEFRAMES period, // Specified Position Period - XPositionPack &pack // Hold Result - ) - { - // - bool result = false; - - // - pack.Clean(); - - // - XPosition position; - bool hasPosition = GetPosition( - ticket, - position - // - ); - if (hasPosition) - { - pack.position = position; - } - - // - XOrder supportOrders[]; - XPosition supportPositions[]; - - // - XOrder orders[]; - GetOrders( - orders, - symbol, // Specified Symbol - NULL, // All Providers - period, // Specified Period - NULL, // All Types - ORDER_STATE_PLACED, // Just UnTriggered Orders - true // Filter by Magic - ); - int ordersCount = ArraySize(orders); - - // - // Select Orders ... - if (ordersCount > 0) - { - // - for (int i = 0; i < ordersCount; i++) - { - // - XOrder iOrder = orders[i]; - - // - // Retrieve Order Supported Ticket ... - ulong parentTicket = ExtractSupportedTicket(iOrder.comment); - if (NotEmpty(parentTicket) && parentTicket == ticket) - { - // - AddRef( - iOrder, - supportOrders - // - ); - } - } - } - - // - int supportOrdersCount = ArraySize(supportOrders); - if (supportOrdersCount > 0) - { - // - pack.supportOrdersCount = supportOrdersCount; - - // - Copy( - supportOrders, - pack.supportOrders); - } - - // - XPosition positions[]; - GetPositions( - positions, - symbol, // Specified Symbol ... - NULL, // All Providers ... - period // Specified Period ... - ); - int positionsCount = ArraySize(positions); - - // - // Select Positions ... - if (positionsCount > 0) - { - // - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - ulong parentTicket = ExtractSupportedTicket(iPosition.comment); - if (NotEmpty(parentTicket) && parentTicket == ticket) - { - // - AddRef( - iPosition, - supportPositions - // - ); - } - } - } - - // - int supportPositionsCount = ArraySize(supportPositions); - if (supportPositionsCount > 0) - { - // - pack.supportPositionsCount = supportPositionsCount; - - // - Copy( - supportPositions, - pack.supportPositions); - } - - // - result = supportOrdersCount > 0 || supportPositionsCount > 0; - - // - return result; - } - // // Extract Specific Deals Position's Pack ... // this used when a Position SL or TP triggered and we want to close diff --git a/Experts/x-test.x121ea.mq5 b/Experts/x-test.x121ea.mq5 index e52e3b2b..6b8fb7f7 100644 --- a/Experts/x-test.x121ea.mq5 +++ b/Experts/x-test.x121ea.mq5 @@ -27,6 +27,7 @@ // // "EURUSDb,USDCHFb,USDJPYb,XAUUSDb" +// "EURUSDb,USDCHFb,USDJPYb,GBPUSDb,XAUUSDb,AUDUSDb,USDCADb,NZDUSDb" // // Inputs ... @@ -34,14 +35,14 @@ long x121EAMagicNumber = 78692110; int x121EASlippage = 10; // Slippgae string x121EASymbols = "EURUSDb,USDCHFb,USDJPYb,GBPUSDb,XAUUSDb,AUDUSDb,USDCADb,NZDUSDb"; // Symbols // -bool x121EAAllowLong = true; // Allow Long Trades -bool x121EAAllowShort = true; // Allow Short Trades -int x121EAManageInterval = 5; // Manager Check Intervals Seconds -int x121EAMaxAllowedPositions = 30; // Max Allowed Positions -double x121EAMaxAllowedSpread = 0; // Max Allowed Spred for Opening Trades -double x121EAMinProfitPerTrade = 0.3; // Min Profit Per Trade based On Volume Factor (Hedge) -double x121EAMinProfitPerVolumeFactor = 0.01; // Min Volume Factor for Calculating Profit (Hedge) -double x121EAMaxAllowedDrawdownFactor = 0.05; // Max Allowed Drawdown Factor +bool x121EAAllowLong = true; // Allow Long Trades +bool x121EAAllowShort = true; // Allow Short Trades +int x121EAManageInterval = 0; // Manager Check Intervals Seconds +int x121EAMaxAllowedPositions = 5; // Max Allowed Positions +double x121EAMaxAllowedSpread = 0; // Max Allowed Spred for Opening Trades +double x121EAMinProfitPerTrade = 0.5; // Min Profit Per Trade based On Volume Factor (Hedge) +double x121EAMinProfitPerVolumeFactor = 0.01; // Min Volume Factor for Calculating Profit (Hedge) +double x121EAMaxAllowedDrawdownFactor = 0.002; // Max Allowed Drawdown Factor // double x121EAVolume = 0.01; @@ -193,6 +194,8 @@ bool InitialEA() Add(X786, signallers); Add(X110, signallers); Add(X121, signallers); + Add(X128, signallers); + Add(X92, signallers); // GetAllX121SignalProviders(signallers); // @@ -265,7 +268,7 @@ bool InitialEA() // // XPV ... - iDescriptor.inputs.pvInputs.showPeaksAndVales = false; + iDescriptor.inputs.pvInputs.showPeaksAndVales = true; iDescriptor.inputs.pvInputs.showLevels = false; iDescriptor.inputs.pvInputs.showConsolidations = false; iDescriptor.inputs.pvInputs.showFibo1Levels = false; diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 index fed2da02..904da6f4 100644 --- a/Libraries/x-saherelm.xtrade.lib.mq5 +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -3571,6 +3571,107 @@ int FindIndex( return result; } +// +// +// Calculate Positions Profit Summary ... +double SpecifiedCalculatePositionsProfit( + XPosition &positions[] // Source +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result += iPosition.profit; + } + + // + return result; +} + +// +// Calculate Required Profit for Hedging ... +double SpecifiedCalculateRequiredProfitForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; + if (!isHedgingEnable) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) + { + // + result += + ((iPosition.volume / mMinProfitPerVolumeFactor) * + mMinProfitPerTrade) + + (-1 * iPosition.swap); + } + } + + // + return result; +} + +// +bool SpecifiedIsPositionsReadyForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + bool result = requiredProfit > 0 + ? profit >= requiredProfit + : profit > requiredProfit; + + // + return result; +} + // // Retrieve String Representation ... string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value)